// // Write SCD4x sensor values into a JSON file // written by Larry Bank Feb 13, 2026 // #include #include #include #include #include #include #include #include SCD41 co2; // Structure holding all of the info for a JSON sensor record typedef struct tagjsonrec { const char *szMake; const char *szModel; const char *szKind; const char *szValue; const char *szUnit; } JSONREC; // Enumerated value indicating the position of the record in the JSON // We need this to know where to start/end the nested curly braces enum { REC_INVALID = 0, REC_FIRST, REC_ANY, REC_LAST }; // // Add one item to the JSON file // f - an open file handle // pRec - pointer to a JSONREC structure // iRecOrder - indicates if this is the first, middle or last value // void AddJSONItem(FILE *f, JSONREC *pRec, int iRecOrder) { time_t tt; char szOut[1024], szTemp[256]; tt = time(NULL); // get the current system time if (iRecOrder == REC_FIRST) { strcpy(szOut, "{\n \"data\": [\n {\n"); } else { strcpy(szOut, " {\n"); } sprintf(szTemp, " \"make\": \"%s\",\n \"model\": \"%s\",\n", pRec->szMake, pRec->szModel); strcat(szOut, szTemp); sprintf(szTemp, " \"kind\": \"%s\",\n \"value\": %s,\n", pRec->szKind, pRec->szValue); strcat(szOut, szTemp); sprintf(szTemp, " \"unit\": \"%s\",\n", pRec->szUnit); strcat(szOut, szTemp); sprintf(szTemp, " \"created_at\": %lu\n }", (unsigned long)tt); strcat(szOut, szTemp); if (iRecOrder == REC_LAST) { strcat(szOut, "\n ]\n}\n"); } else { strcat(szOut, ",\n"); } fwrite(szOut, 1, strlen(szOut), f); } /* AddJSONItem() */ int main(int argc, char *argv[]) { int i, iBus; DIR *pDir; struct dirent *pDE; uint32_t u32Buses = 0; // available I2C bus numbers (0-31) JSONREC rec; printf("sensor2json example\n"); printf("Finds which I2C bus has the supported sensor, then\ninitializes, configures, and loops updating the json with the latest sensor values.\n"); if (argc != 2) { printf("usage: sensor2json \n"); return -1; } // I2C buses in Linux are defined as a file in the /dev directory pDir = opendir("/dev"); if (!pDir) { printf("Error searching /dev directory; aborting.\n"); return -1; } // Search all names in the /dev directory for those starting with i2c- while ((pDE = readdir(pDir)) != NULL) { if (memcmp(pDE->d_name, "i2c-", 4) == 0) { // found one! iBus = atoi(&pDE->d_name[4]); u32Buses |= (1 << iBus); // collect the bus numbers } } closedir(pDir); if (u32Buses == 0) { // Something went wrong; no I2C buses printf("No I2C buses found!\n"); printf("Check your system configuration (e.g. raspi-config)\n"); printf("to ensure that I2C is enabled.\n"); return -1; } // Search each I2C bus for a supported proximited sensor for (iBus=0; iBus<32; iBus++) { if (u32Buses & (1<