feat(spectro): add instlist utility for JSON instrument enumeration #9
@@ -52,6 +52,7 @@ Test 1D Brent solver
|
|||||||
<br>xicc/xcolorantslu.exe
|
<br>xicc/xcolorantslu.exe
|
||||||
<br>xicc/xfbview.exe
|
<br>xicc/xfbview.exe
|
||||||
<br>spectro/dispwin.exe
|
<br>spectro/dispwin.exe
|
||||||
|
<br>spectro/instlist.exe
|
||||||
<br>target/ifarp.exe
|
<br>target/ifarp.exe
|
||||||
<br>target/ppoint.exe
|
<br>target/ppoint.exe
|
||||||
<br>target/qrand.exe
|
<br>target/qrand.exe
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>instlist</title>
|
||||||
|
<meta http-equiv="content-type" content="text/html;
|
||||||
|
charset=windows-1252">
|
||||||
|
<meta name="author" content="Graeme Gill">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2><b>spectro/instlist</b></h2>
|
||||||
|
<br>
|
||||||
|
Enumerate connected instrument communication ports (USB and Serial) and output the list in JSON format.<br>
|
||||||
|
<h3>Usage</h3>
|
||||||
|
<small><span style="font-family: monospace;"> instlist [-options]</span><br style="font-family: monospace;">
|
||||||
|
<span style="font-family: monospace;"> -h, -?, --help Show help information</span><br style="font-family: monospace;">
|
||||||
|
<span style="font-family: monospace;"> -v Verbose diagnostics to stderr</span><br style="font-family: monospace;">
|
||||||
|
<span style="font-family: monospace;"> -D [level] Print debug diagnostics to stderr</span><br style="font-family: monospace;">
|
||||||
|
</small><br>
|
||||||
|
<h3><b>Output</b></h3>
|
||||||
|
The output is emitted to <code>stdout</code> as a JSON object containing an array of discovered device objects:<br>
|
||||||
|
<pre>
|
||||||
|
{
|
||||||
|
"event": "instruments",
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"port": 1,
|
||||||
|
"name": "usb:/bus0/dev1 (X-Rite i1Pro)",
|
||||||
|
"type": "i1Pro"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<h3>Comments</h3>
|
||||||
|
This tool is designed to allow graphical user interfaces and external automation scripts to discover available spectrophotometers and colorimeters across Windows, macOS, and Linux without needing to parse interactive usage output.<br>
|
||||||
|
<br>
|
||||||
|
The <code>port</code> number directly corresponds to the <code>-c</code> parameter accepted by tools such as <a href="chartread.html">chartread</a>, <a href="spotread.html">spotread</a>, and <a href="dispread.html">dispread</a>.<br>
|
||||||
|
<br>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -42,6 +42,7 @@ LINKLIBS = ../numlib/libnum ;
|
|||||||
# GenFile source.c : program args ; make custom file
|
# GenFile source.c : program args ; make custom file
|
||||||
# Generate all the kernel files
|
# Generate all the kernel files
|
||||||
GenFileND imdi_k.h : imdi_make $(IMDI_MAKE_OPT) -d [ NormPaths $(DOT) ] ;
|
GenFileND imdi_k.h : imdi_make $(IMDI_MAKE_OPT) -d [ NormPaths $(DOT) ] ;
|
||||||
|
Clean clean : imdi_k.c ;
|
||||||
|
|
||||||
# imdi library
|
# imdi library
|
||||||
Library libimdi : imdi.c imdi_tab.c ;
|
Library libimdi : imdi.c imdi_tab.c ;
|
||||||
|
|||||||
+5
-1
@@ -51,7 +51,7 @@ if $(UNIX) {
|
|||||||
#Products
|
#Products
|
||||||
Libraries = libinsttypes libdisptechs libinst libdisp libconv libinstapp ;
|
Libraries = libinsttypes libdisptechs libinst libdisp libconv libinstapp ;
|
||||||
Executables = dispwin synthcal dispread dispcal fakeread synthread
|
Executables = dispwin synthcal dispread dispcal fakeread synthread
|
||||||
chartread spotread illumread ccxxmake average oeminst ;
|
chartread spotread instlist illumread ccxxmake average oeminst ;
|
||||||
Headers = inst.h ;
|
Headers = inst.h ;
|
||||||
Samples = SOtele.sp linear.cal strange.cal ccxx.ti1 ;
|
Samples = SOtele.sp linear.cal strange.cal ccxx.ti1 ;
|
||||||
|
|
||||||
@@ -198,6 +198,10 @@ Main illumread : illumread.c : : : ../target : : ;
|
|||||||
# Printed target spot reader utility
|
# Printed target spot reader utility
|
||||||
Main spotread : spotread.c : : : : : ;
|
Main spotread : spotread.c : : : : : ;
|
||||||
|
|
||||||
|
# Connected instrument enumeration utility
|
||||||
|
Main instlist : instlist.c : : : : : ;
|
||||||
|
Clean clean : instlist$(SUFEXE) instlist.o ;
|
||||||
|
|
||||||
echo "HOME = " $(HOME) ;
|
echo "HOME = " $(HOME) ;
|
||||||
echo "PWD = " $(PWD) ;
|
echo "PWD = " $(PWD) ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Argyll Color Management System
|
||||||
|
* USB & Serial Instrument Enumeration Utility.
|
||||||
|
* Outputs connected instruments in structured JSON format.
|
||||||
|
*
|
||||||
|
* Author: Graeme W. Gill / Gordon
|
||||||
|
*
|
||||||
|
* Copyright 2026 Graeme W. Gill / Gordon
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
|
||||||
|
* see the License.txt file for licencing details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "copyright.h"
|
||||||
|
#include "aconfig.h"
|
||||||
|
#include "numlib.h"
|
||||||
|
#include "cgats.h"
|
||||||
|
#include "conv.h"
|
||||||
|
#include "xicc.h"
|
||||||
|
#include "insttypes.h"
|
||||||
|
#include "icoms.h"
|
||||||
|
#include "inst.h"
|
||||||
|
|
||||||
|
static void usage(char *diag, ...) {
|
||||||
|
fprintf(stderr,"Enumerate Instrument Ports, Version %s\n",ARGYLL_VERSION_STR);
|
||||||
|
if (diag != NULL) {
|
||||||
|
va_list args;
|
||||||
|
fprintf(stderr," Diagnostic: ");
|
||||||
|
va_start(args, diag);
|
||||||
|
vfprintf(stderr, diag, args);
|
||||||
|
va_end(args);
|
||||||
|
fprintf(stderr,"\n");
|
||||||
|
}
|
||||||
|
fprintf(stderr,"Author: Graeme W. Gill / Gordon, licensed under the AGPL Version 3\n");
|
||||||
|
fprintf(stderr,"usage: instlist [-options]\n");
|
||||||
|
fprintf(stderr," -h, -?, --help Show this help information\n");
|
||||||
|
fprintf(stderr," -v Verbose diagnostics to stderr\n");
|
||||||
|
fprintf(stderr," -D [level] Print debug diagnostics to stderr\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int fa, nfa;
|
||||||
|
int verb = 0;
|
||||||
|
int debug = 0;
|
||||||
|
icompaths *icmps = NULL;
|
||||||
|
icompath **paths = NULL;
|
||||||
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
/* Set executable path for logger */
|
||||||
|
set_exe_path(argv[0]);
|
||||||
|
|
||||||
|
/* Process command-line options */
|
||||||
|
for (fa = 1; fa < argc; fa++) {
|
||||||
|
nfa = fa + 1;
|
||||||
|
if (argv[fa][0] == '-') {
|
||||||
|
char *na = NULL;
|
||||||
|
if (nfa < argc && argv[nfa][0] != '-')
|
||||||
|
na = argv[nfa];
|
||||||
|
|
||||||
|
if (strcmp(argv[fa], "-h") == 0 || strcmp(argv[fa], "-?") == 0 ||
|
||||||
|
strcmp(argv[fa], "--help") == 0 || strcmp(argv[fa], "-help") == 0) {
|
||||||
|
usage(NULL);
|
||||||
|
} else if (argv[fa][1] == 'v') {
|
||||||
|
verb = 1;
|
||||||
|
g_log->verb = verb;
|
||||||
|
} else if (argv[fa][1] == 'D') {
|
||||||
|
debug = 1;
|
||||||
|
if (na != NULL && na[0] >= '0' && na[0] <= '9') {
|
||||||
|
debug = atoi(na);
|
||||||
|
fa = nfa;
|
||||||
|
}
|
||||||
|
g_log->debug = debug;
|
||||||
|
} else {
|
||||||
|
usage("Unknown option '%s'", argv[fa]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
usage("Unexpected argument '%s'", argv[fa]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((icmps = new_icompaths(g_log)) == NULL) {
|
||||||
|
printf("{\n \"event\": \"instruments\",\n \"devices\": []\n}\n");
|
||||||
|
fflush(stdout);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
paths = icmps->paths;
|
||||||
|
|
||||||
|
printf("{\n \"event\": \"instruments\",\n \"devices\": [\n");
|
||||||
|
|
||||||
|
if (paths != NULL) {
|
||||||
|
for (i = 0; paths[i] != NULL; i++) {
|
||||||
|
char *tname = inst_name(paths[i]->dtype);
|
||||||
|
char *name = paths[i]->name ? paths[i]->name : "Unknown";
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
printf(",\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" {\n");
|
||||||
|
printf(" \"port\": %d,\n", i + 1);
|
||||||
|
printf(" \"name\": \"");
|
||||||
|
/* Escape quotes and backslashes in name */
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
for (p = name; *p != '\0'; p++) {
|
||||||
|
if (*p == '"' || *p == '\\') {
|
||||||
|
putchar('\\');
|
||||||
|
}
|
||||||
|
putchar(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\",\n");
|
||||||
|
printf(" \"type\": \"%s\"\n", (tname != NULL && tname[0] != '\0') ? tname : "Unknown");
|
||||||
|
printf(" }");
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n ]\n}\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
if (icmps != NULL)
|
||||||
|
icmps->del(icmps);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user