From be2eb89b71c61034080e36710c67c8566c3bee04 Mon Sep 17 00:00:00 2001 From: Richard Dominick Date: Wed, 30 Mar 2022 02:47:48 +0800 Subject: [PATCH 01/10] Added structs for monitoring; sample function to run shell commands --- common/sling_message.h | 14 ++++++++++++++ linux/src/main.c | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/common/sling_message.h b/common/sling_message.h index 26bde08..7451d0f 100644 --- a/common/sling_message.h +++ b/common/sling_message.h @@ -13,6 +13,20 @@ #define SLING_OUTTOPIC_STATUS "status" #define SLING_OUTTOPIC_DISPLAY "display" #define SLING_OUTTOPIC_HELLO "hello" +#define SLING_OUTTOPIC_MONITOR "monitor" + +struct __attribute__((packed)) sling_message_monitor_flush { + uint32_t message_counter; + uint32_t starting_id; +}; +_Static_assert(sizeof(struct sling_message_monitor_flush) == 8, "Wrong sling_message_monitor_flush size"); + +struct __attribute__((packed)) sling_message_monitor { + uint32_t message_counter; + uint32_t string_length; + char string[]; +}; +_Static_assert(sizeof(struct sling_message_monitor) == 8, "Wrong sling_message_monitor size"); enum sling_message_status_type { sling_message_status_type_idle = 0, diff --git a/linux/src/main.c b/linux/src/main.c index 9ca0d76..e045182 100644 --- a/linux/src/main.c +++ b/linux/src/main.c @@ -41,6 +41,7 @@ struct sling_config { char *outtopic_status; char *outtopic_display; char *outtopic_hello; + char *outtopic_monitor; char *intopic_run; char *intopic_stop; @@ -279,6 +280,27 @@ static void main_loop_epoll_add(enum main_loop_epoll_type type, int fd) { check_posix(epoll_ctl(config.epollfd, EPOLL_CTL_ADD, fd, &ev), "epoll_ctl"); } +static void get_peripherals() { + FILE *fp; + char path[1035]; + + /* Open the command for reading. */ + fp = popen("/bin/ls /etc/", "r"); + if (fp == NULL) { +// printf("Failed to run command\n" ); +// exit(1); + return; + } + + /* Read the output a line at a time - output it. */ + while (fgets(path, sizeof(path), fp) != NULL) { + printf("%s", path); + } + + /* close */ + pclose(fp); +} + static int main_loop(void) { size_t buffer_size = 0x4000; char *buffer = malloc(buffer_size); @@ -500,6 +522,7 @@ int main(int argc, char *argv[]) { config.outtopic_display = sling_topic(config.device_id, SLING_OUTTOPIC_DISPLAY); config.outtopic_status = sling_topic(config.device_id, SLING_OUTTOPIC_STATUS); config.outtopic_hello = sling_topic(config.device_id, SLING_OUTTOPIC_HELLO); + config.outtopic_monitor = sling_topic(config.device_id, SLING_OUTTOPIC_MONITOR); config.intopic_input = sling_topic(config.device_id, SLING_INTOPIC_INPUT); config.intopic_ping = sling_topic(config.device_id, SLING_INTOPIC_PING); From 11e2a732d6e7bc4f49ad74d2d78a46d990803b6f Mon Sep 17 00:00:00 2001 From: Richard Dominick Date: Sun, 3 Apr 2022 05:51:13 +0800 Subject: [PATCH 02/10] Implement draft `monitor` topic --- linux/src/main.c | 59 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/linux/src/main.c b/linux/src/main.c index e045182..11dfb3d 100644 --- a/linux/src/main.c +++ b/linux/src/main.c @@ -59,7 +59,9 @@ struct sling_config { uint32_t message_counter; uint32_t display_start_counter; - uint32_t last_flush_counter; + uint32_t last_display_flush_counter; + uint32_t monitor_start_counter; +// uint32_t last_monitor_flush_counter; // MUST BE POWER OF 2 #define LAST_MESSAGE_ID_BUF_SIZE 4 @@ -282,19 +284,47 @@ static void main_loop_epoll_add(enum main_loop_epoll_type type, int fd) { static void get_peripherals() { FILE *fp; - char path[1035]; + char buffer[256]; - /* Open the command for reading. */ - fp = popen("/bin/ls /etc/", "r"); + /* Read motors */ + // for f in /sys/class/lego-sensor/*; do cat $f/{address,driver_name,mode,value0}; done +// fp = popen("for f in /sys/class/tacho-motor/*; do cat $f/{address,driver_name,position,speed}; done", "r"); + fp = popen("for f in /sys/class/tacho-motor/*; do cat $f/{address,driver_name,position,speed}; done; for f in /sys/class/lego-sensor/*; do cat $f/{address,driver_name,mode,value0}; done", "r"); if (fp == NULL) { -// printf("Failed to run command\n" ); -// exit(1); return; } - /* Read the output a line at a time - output it. */ - while (fgets(path, sizeof(path), fp) != NULL) { - printf("%s", path); + /* Read the output a line at a time. */ + uint8_t line_count = 0; + while (fgets(buffer, sizeof(buffer), fp) != NULL) { +// printf("%s", path); + + ++line_count; + + uint32_t recv_size = strlen(buffer); + + struct sling_message_monitor *to_send = (struct sling_message_monitor *) buffer; + to_send->message_counter = config.message_counter; + to_send->string_length = recv_size; + + if (line_count == 1) { + config.monitor_start_counter = config.message_counter; + } + + ++config.message_counter; + check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size, buffer, 1, false)); + + if (line_count == 4) { // flush - expect 4 lines for each motor + // TODO + struct sling_message_monitor_flush *to_send = {0}; + to_send->message_counter = config.message_counter; + to_send->starting_id = config.monitor_start_counter; + + check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size, buffer, 1, false)); + + ++config.message_counter; + line_count = 0; + } } /* close */ @@ -324,6 +354,8 @@ static int main_loop(void) { main_loop_epoll_add(main_loop_epoll_child, sigchldfd); while (1) { + get_peripherals(); + int nfds = check_posix(epoll_wait(config.epollfd, events, max_events, 1000), "epoll_wait"); for (int n = 0; n < nfds; ++n) { struct epoll_event *ev = events + n; @@ -363,14 +395,14 @@ static int main_loop(void) { } struct sling_message_display_flush *to_send_flush = (struct sling_message_display_flush *) buffer; to_send_flush->starting_id = config.display_start_counter; - config.last_flush_counter = to_send->message_counter; + config.last_display_flush_counter = to_send->message_counter; recv_size = sizeof(*to_send_flush); - } else if (config.display_start_counter <= config.last_flush_counter) { + } else if (config.display_start_counter <= config.last_display_flush_counter) { config.display_start_counter = to_send->message_counter; } if (to_send->display_type & sling_message_display_type_self_flushing) { - config.last_flush_counter = to_send->message_counter; + config.last_display_flush_counter = to_send->message_counter; } ++config.message_counter; @@ -423,7 +455,8 @@ int main(int argc, char *argv[]) { config.client_cert_path = getenv("SLING_CERT"); config.sinter_host_path = getenv("SINTER_HOST_PATH"); config.program_path = getenv("SLING_PROGRAM_PATH"); - config.message_counter = config.last_flush_counter = config.display_start_counter = 0; + config.message_counter = config.last_display_flush_counter = config.display_start_counter = config.monitor_start_counter = 0; +// config.message_counter = config.last_display_flush_counter = config.display_start_counter = config.monitor_start_counter = config.last_monitor_flush_counter = 0; while (1) { static struct option long_options[] = { From 6d5bf6270e6ec73012af3d131fb7a58767a0e91c Mon Sep 17 00:00:00 2001 From: Richard Dominick Date: Wed, 13 Apr 2022 00:03:36 +0800 Subject: [PATCH 03/10] Fix script for POSIX shell --- linux/src/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/linux/src/main.c b/linux/src/main.c index 11dfb3d..3c26030 100644 --- a/linux/src/main.c +++ b/linux/src/main.c @@ -286,10 +286,8 @@ static void get_peripherals() { FILE *fp; char buffer[256]; - /* Read motors */ - // for f in /sys/class/lego-sensor/*; do cat $f/{address,driver_name,mode,value0}; done -// fp = popen("for f in /sys/class/tacho-motor/*; do cat $f/{address,driver_name,position,speed}; done", "r"); - fp = popen("for f in /sys/class/tacho-motor/*; do cat $f/{address,driver_name,position,speed}; done; for f in /sys/class/lego-sensor/*; do cat $f/{address,driver_name,mode,value0}; done", "r"); + /* Read motors and sensors */ + fp = popen("set -- address driver_name position speed; for f in /sys/class/tacho-motor/*; do for item in \"$@\"; do cat \"$f\"/$item; done; done; set -- address driver_name mode value0; for f in /sys/class/lego-sensor/*; do for item in \"$@\"; do cat \"$f\"/$item; done; done", "r"); if (fp == NULL) { return; } From 760a171b56c576b82a8007750358d1540bf1013f Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Tue, 20 Sep 2022 15:56:36 +0800 Subject: [PATCH 04/10] Fix bugs and clean up code --- common/sling_message.h | 3 +-- linux/src/main.c | 37 +++++++------------------------------ 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/common/sling_message.h b/common/sling_message.h index 7451d0f..85409c5 100644 --- a/common/sling_message.h +++ b/common/sling_message.h @@ -23,10 +23,9 @@ _Static_assert(sizeof(struct sling_message_monitor_flush) == 8, "Wrong sling_mes struct __attribute__((packed)) sling_message_monitor { uint32_t message_counter; - uint32_t string_length; char string[]; }; -_Static_assert(sizeof(struct sling_message_monitor) == 8, "Wrong sling_message_monitor size"); +_Static_assert(sizeof(struct sling_message_monitor) == 4, "Wrong sling_message_monitor size"); enum sling_message_status_type { sling_message_status_type_idle = 0, diff --git a/linux/src/main.c b/linux/src/main.c index 3c26030..6b443a0 100644 --- a/linux/src/main.c +++ b/linux/src/main.c @@ -61,7 +61,6 @@ struct sling_config { uint32_t display_start_counter; uint32_t last_display_flush_counter; uint32_t monitor_start_counter; -// uint32_t last_monitor_flush_counter; // MUST BE POWER OF 2 #define LAST_MESSAGE_ID_BUF_SIZE 4 @@ -287,7 +286,7 @@ static void get_peripherals() { char buffer[256]; /* Read motors and sensors */ - fp = popen("set -- address driver_name position speed; for f in /sys/class/tacho-motor/*; do for item in \"$@\"; do cat \"$f\"/$item; done; done; set -- address driver_name mode value0; for f in /sys/class/lego-sensor/*; do for item in \"$@\"; do cat \"$f\"/$item; done; done", "r"); + fp = popen("set -- address driver_name position speed; for f in /sys/class/tacho-motor/*; do for item in $@; do cat $f/$item; done; done; set -- address driver_name mode value0; for f in /sys/class/lego-sensor/*; do for item in $@; do cat $f/$item; done; done", "r"); if (fp == NULL) { return; } @@ -295,37 +294,17 @@ static void get_peripherals() { /* Read the output a line at a time. */ uint8_t line_count = 0; while (fgets(buffer, sizeof(buffer), fp) != NULL) { -// printf("%s", path); - ++line_count; - uint32_t recv_size = strlen(buffer); - struct sling_message_monitor *to_send = (struct sling_message_monitor *) buffer; - to_send->message_counter = config.message_counter; - to_send->string_length = recv_size; - - if (line_count == 1) { - config.monitor_start_counter = config.message_counter; - } - - ++config.message_counter; - check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size, buffer, 1, false)); + char out[recv_size + 4]; + struct sling_message_monitor *to_send = (struct sling_message_monitor *) out; + to_send->message_counter = config.message_counter++; + strcpy(to_send->string, buffer); - if (line_count == 4) { // flush - expect 4 lines for each motor - // TODO - struct sling_message_monitor_flush *to_send = {0}; - to_send->message_counter = config.message_counter; - to_send->starting_id = config.monitor_start_counter; - - check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size, buffer, 1, false)); - - ++config.message_counter; - line_count = 0; - } + send_hello_if_zero(); + check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size + 4, to_send, 1, false)); } - - /* close */ pclose(fp); } @@ -353,7 +332,6 @@ static int main_loop(void) { while (1) { get_peripherals(); - int nfds = check_posix(epoll_wait(config.epollfd, events, max_events, 1000), "epoll_wait"); for (int n = 0; n < nfds; ++n) { struct epoll_event *ev = events + n; @@ -454,7 +432,6 @@ int main(int argc, char *argv[]) { config.sinter_host_path = getenv("SINTER_HOST_PATH"); config.program_path = getenv("SLING_PROGRAM_PATH"); config.message_counter = config.last_display_flush_counter = config.display_start_counter = config.monitor_start_counter = 0; -// config.message_counter = config.last_display_flush_counter = config.display_start_counter = config.monitor_start_counter = config.last_monitor_flush_counter = 0; while (1) { static struct option long_options[] = { From e9f9c39f4ee3e93d2b8fc96e3f235c7f9eb3b7fc Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Tue, 20 Sep 2022 16:20:05 +0800 Subject: [PATCH 05/10] Add flushing every 4 lines --- common/sling_message.h | 6 ++++-- linux/src/main.c | 22 +++++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/common/sling_message.h b/common/sling_message.h index 85409c5..8a45717 100644 --- a/common/sling_message.h +++ b/common/sling_message.h @@ -17,15 +17,17 @@ struct __attribute__((packed)) sling_message_monitor_flush { uint32_t message_counter; + uint8_t is_flush; uint32_t starting_id; }; -_Static_assert(sizeof(struct sling_message_monitor_flush) == 8, "Wrong sling_message_monitor_flush size"); +_Static_assert(sizeof(struct sling_message_monitor_flush) == 9, "Wrong sling_message_monitor_flush size"); struct __attribute__((packed)) sling_message_monitor { uint32_t message_counter; + uint8_t is_flush; char string[]; }; -_Static_assert(sizeof(struct sling_message_monitor) == 4, "Wrong sling_message_monitor size"); +_Static_assert(sizeof(struct sling_message_monitor) == 5, "Wrong sling_message_monitor size"); enum sling_message_status_type { sling_message_status_type_idle = 0, diff --git a/linux/src/main.c b/linux/src/main.c index 6b443a0..66de9d4 100644 --- a/linux/src/main.c +++ b/linux/src/main.c @@ -297,13 +297,29 @@ static void get_peripherals() { ++line_count; uint32_t recv_size = strlen(buffer); - char out[recv_size + 4]; + if (line_count == 1) { + config.monitor_start_counter = config.message_counter; + } + + char out[recv_size + sizeof(struct sling_message_monitor)]; struct sling_message_monitor *to_send = (struct sling_message_monitor *) out; to_send->message_counter = config.message_counter++; + to_send->is_flush = 0; strcpy(to_send->string, buffer); send_hello_if_zero(); - check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size + 4, to_send, 1, false)); + check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size + sizeof(struct sling_message_monitor), to_send, 1, false)); + + if (line_count == 4) { // We always expect 4 lines for each peripheral + char out[sizeof(struct sling_message_monitor_flush)]; + struct sling_message_monitor_flush *flush_monitor = (struct sling_message_monitor_flush *) out; + flush_monitor->message_counter = config.message_counter++; + flush_monitor->is_flush = 1; + flush_monitor->starting_id = config.monitor_start_counter; + check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, sizeof(struct sling_message_monitor_flush), flush_monitor, 1, false)); + + line_count = 0; + } } pclose(fp); } @@ -331,7 +347,7 @@ static int main_loop(void) { main_loop_epoll_add(main_loop_epoll_child, sigchldfd); while (1) { - get_peripherals(); + get_peripherals(); // int nfds = check_posix(epoll_wait(config.epollfd, events, max_events, 1000), "epoll_wait"); for (int n = 0; n < nfds; ++n) { struct epoll_event *ev = events + n; From a0621002f09168a9dbd08196bcd3c33636c1765f Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Tue, 20 Sep 2022 16:45:37 +0800 Subject: [PATCH 06/10] Remove newline from monitor payloads --- linux/src/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux/src/main.c b/linux/src/main.c index 66de9d4..49e670d 100644 --- a/linux/src/main.c +++ b/linux/src/main.c @@ -297,6 +297,11 @@ static void get_peripherals() { ++line_count; uint32_t recv_size = strlen(buffer); + if (buffer[recv_size - 1] == '\n') { + buffer[recv_size - 1] = '\0'; + --recv_size; + } + if (line_count == 1) { config.monitor_start_counter = config.message_counter; } From 69121574aff85884330b84ba6677e35c68677d42 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Tue, 20 Sep 2022 16:46:43 +0800 Subject: [PATCH 07/10] Reduce line buffer size --- linux/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/src/main.c b/linux/src/main.c index 49e670d..952fe7c 100644 --- a/linux/src/main.c +++ b/linux/src/main.c @@ -283,7 +283,7 @@ static void main_loop_epoll_add(enum main_loop_epoll_type type, int fd) { static void get_peripherals() { FILE *fp; - char buffer[256]; + char buffer[64]; /* Read motors and sensors */ fp = popen("set -- address driver_name position speed; for f in /sys/class/tacho-motor/*; do for item in $@; do cat $f/$item; done; done; set -- address driver_name mode value0; for f in /sys/class/lego-sensor/*; do for item in $@; do cat $f/$item; done; done", "r"); From 8539c0c0ddd2085d2f39112b8ad69d6f0a2b587f Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Wed, 21 Sep 2022 21:24:11 +0800 Subject: [PATCH 08/10] Update Sling JS client --- client-js/package.json | 2 +- client-js/src/index.ts | 30 ++++++++++++++++++++++++------ client-js/src/slingProtocol.ts | 32 ++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/client-js/package.json b/client-js/package.json index 5c2a828..46dde6b 100644 --- a/client-js/package.json +++ b/client-js/package.json @@ -1,6 +1,6 @@ { "name": "@sourceacademy/sling-client", - "version": "0.0.1", + "version": "0.1.0", "description": "Sling client.", "main": "dist/index.js", "repository": "https://github.com/source-academy/sling", diff --git a/client-js/src/index.ts b/client-js/src/index.ts index 9ff47a7..e764d02 100644 --- a/client-js/src/index.ts +++ b/client-js/src/index.ts @@ -1,15 +1,16 @@ +import { connect as mqttConnect, MqttClient } from 'mqtt'; import { TypedEmitter } from 'tiny-typed-emitter'; -import { MqttClient, connect as mqttConnect } from 'mqtt'; import { - slingDeviceMessageTypes, deserialiseMqttMessage, + serialiseMqttMessage, + slingDeviceMessageTypes, + SlingDisplayFlushMessage, + SlingDisplayMessageType, SlingMessage, SlingMessageType, - serialiseMqttMessage, - SlingOptionalIdMessage, + SlingMonitorNonFlushMessage, SlingNonFlushDisplayMessage, - SlingDisplayFlushMessage, - SlingDisplayMessageType + SlingOptionalIdMessage } from './slingProtocol'; export interface SlingClientOptions { @@ -34,6 +35,7 @@ export interface SlingClientEvents { error: (error: Error) => void; message: (message: SlingMessage) => void; statusChange: (isRunning: boolean) => void; + monitor: (data: string[]) => void; prompt: (prompt: string) => void; promptDismiss: () => void; display: ( @@ -57,6 +59,8 @@ export class SlingClient extends TypedEmitter { private readonly _displayBuffer = new Map(); private readonly _queuedFlushes = new Set(); + private _monitorData: string[] = []; + constructor(options: SlingClientOptions) { super(); this.options = options; @@ -185,6 +189,20 @@ export class SlingClient extends TypedEmitter { break; } + case SlingMessageType.MONITOR: { + if (message.isFlush) { + if (this._monitorData.length === 4) { + // Only emit update when message is complete + this.emit('monitor', this._monitorData); + } + this._monitorData = []; + } else { + const msg = message as SlingMonitorNonFlushMessage; + this._monitorData.push(msg.data); + } + break; + } + case SlingMessageType.DISPLAY: { if (message.selfFlushing && message.displayType !== 'flush') { this.emit('display', message.value, message.displayType); diff --git a/client-js/src/slingProtocol.ts b/client-js/src/slingProtocol.ts index 1cdfcaa..bc3f163 100644 --- a/client-js/src/slingProtocol.ts +++ b/client-js/src/slingProtocol.ts @@ -1,4 +1,4 @@ -import { SerialiserEntry, serialise } from './serialiser'; +import { serialise, SerialiserEntry } from './serialiser'; function flip(o: Record): Record { // TODO fixme @@ -13,13 +13,15 @@ export const enum SlingMessageType { STATUS = 'status', DISPLAY = 'display', INPUT = 'input', - HELLO = 'hello' + HELLO = 'hello', + MONITOR = 'monitor' } export const slingDeviceMessageTypes = [ SlingMessageType.DISPLAY, SlingMessageType.STATUS, - SlingMessageType.HELLO + SlingMessageType.HELLO, + SlingMessageType.MONITOR ]; export const slingClientMessageTypes = [ SlingMessageType.RUN, @@ -106,6 +108,19 @@ export type SlingNonFlushDisplayMessage = export type SlingDisplayMessage = SlingNonFlushDisplayMessage | SlingDisplayFlushMessage; +export interface SlingMonitorNonFlushMessage extends SlingEmptyMessage { + isFlush: boolean; + data: string; +} + +export interface SlingMonitorFlushMessage extends SlingEmptyMessage { + isFlush: boolean; + startingId: number; + endingId: number; +} + +export type SlingMonitorMessage = SlingMonitorFlushMessage | SlingMonitorNonFlushMessage; + export type SlingStatus = keyof typeof slingStatusToId; const slingStatusToId = { @@ -133,7 +148,8 @@ export type SlingNoIdMessage = | SlingStatusMessage | SlingStopMessage | SlingPingMessage - | SlingHelloMessage; + | SlingHelloMessage + | SlingMonitorMessage; export type SlingOptionalIdMessage = SlingNoIdMessage & { id?: number }; export type SlingMessage = SlingNoIdMessage & { id: number }; @@ -184,6 +200,14 @@ export function deserialiseMqttMessage(topic: string, data: Buffer): SlingMessag return { id, type }; case SlingMessageType.RUN: return { id, type, code: data.slice(4) }; + case SlingMessageType.MONITOR: { + const isFlush = data.readUInt8(4) === 1; + const common = { id, type, isFlush }; + if (isFlush) { + return { ...common, startingId: data.readUInt32LE(5), endingId: id }; + } + return { ...common, data: data.slice(5).toString() }; + } case SlingMessageType.STATUS: { const status = slingStatusById[data.readUInt16LE(4)]; if (!status) { From 5e438c3db39b2c2ee4abd06e3d0db549832ba3fe Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Wed, 21 Sep 2022 21:26:58 +0800 Subject: [PATCH 09/10] Update gitignore --- .gitignore | 1 + linux/.gitignore | 1 + 2 files changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/linux/.gitignore b/linux/.gitignore index 378eac2..6be3b8f 100644 --- a/linux/.gitignore +++ b/linux/.gitignore @@ -1 +1,2 @@ build +cmake-build-debug From f8c0474cb555d881b4fb35bfec9ff6c8db152e1e Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Thu, 29 Sep 2022 09:21:25 +0800 Subject: [PATCH 10/10] Rewrite shell function in C --- linux/src/main.c | 104 +++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 34 deletions(-) diff --git a/linux/src/main.c b/linux/src/main.c index 952fe7c..05ea44b 100644 --- a/linux/src/main.c +++ b/linux/src/main.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -22,6 +23,11 @@ #define eprintf(...) fprintf(stderr, __VA_ARGS__) +#define FILENAME_LEN 64 +#define PROPNAME_LEN 12 +#define MOTORS_DIR "/sys/class/tacho-motor/" +#define SENSORS_DIR "/sys/class/lego-sensor/" + typedef enum sling_message_status_type device_status_t; struct sling_config { @@ -281,52 +287,82 @@ static void main_loop_epoll_add(enum main_loop_epoll_type type, int fd) { check_posix(epoll_ctl(config.epollfd, EPOLL_CTL_ADD, fd, &ev), "epoll_ctl"); } +static void read_and_send_peripheral_data(char [], char [][PROPNAME_LEN], int); + static void get_peripherals() { - FILE *fp; - char buffer[64]; + char peripheral[FILENAME_LEN]; + + char motor_drivers[][PROPNAME_LEN] = {"address", "driver_name", "position", "speed"}; + char sensor_drivers[][PROPNAME_LEN] = {"address", "driver_name", "mode", "value0"}; + + DIR *d; + struct dirent *dir; + d = opendir(MOTORS_DIR); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..")) { + snprintf(peripheral, FILENAME_LEN, "%s%s", MOTORS_DIR, dir->d_name); + read_and_send_peripheral_data(peripheral, motor_drivers, 4); + } + } + closedir(d); + } - /* Read motors and sensors */ - fp = popen("set -- address driver_name position speed; for f in /sys/class/tacho-motor/*; do for item in $@; do cat $f/$item; done; done; set -- address driver_name mode value0; for f in /sys/class/lego-sensor/*; do for item in $@; do cat $f/$item; done; done", "r"); - if (fp == NULL) { - return; + d = opendir(SENSORS_DIR); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (strcmp(dir->d_name, ".") && strcmp(dir->d_name, "..")) { + snprintf(peripheral, FILENAME_LEN, "%s%s", SENSORS_DIR, dir->d_name); + read_and_send_peripheral_data(peripheral, sensor_drivers, 4); + } + } + closedir(d); } +} + +static void read_and_send_peripheral_data(char filename[], char prop_names[][PROPNAME_LEN], int props_count) { + char buffer[64]; + char property[FILENAME_LEN]; - /* Read the output a line at a time. */ - uint8_t line_count = 0; - while (fgets(buffer, sizeof(buffer), fp) != NULL) { - ++line_count; - uint32_t recv_size = strlen(buffer); + config.monitor_start_counter = config.message_counter; - if (buffer[recv_size - 1] == '\n') { - buffer[recv_size - 1] = '\0'; - --recv_size; - } - if (line_count == 1) { - config.monitor_start_counter = config.message_counter; + for (int i = 0; i < props_count; ++i) { + FILE *fp; + snprintf(property, FILENAME_LEN, "%s/%s", filename, prop_names[i]); + fp = fopen(property, "r"); + if (fp == NULL) { + break; } - char out[recv_size + sizeof(struct sling_message_monitor)]; - struct sling_message_monitor *to_send = (struct sling_message_monitor *) out; - to_send->message_counter = config.message_counter++; - to_send->is_flush = 0; - strcpy(to_send->string, buffer); + while (fgets(buffer, sizeof(buffer), fp) != NULL) { + uint32_t recv_size = strlen(buffer); - send_hello_if_zero(); - check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size + sizeof(struct sling_message_monitor), to_send, 1, false)); + if (buffer[recv_size - 1] == '\n') { + buffer[recv_size - 1] = '\0'; + --recv_size; + } - if (line_count == 4) { // We always expect 4 lines for each peripheral - char out[sizeof(struct sling_message_monitor_flush)]; - struct sling_message_monitor_flush *flush_monitor = (struct sling_message_monitor_flush *) out; - flush_monitor->message_counter = config.message_counter++; - flush_monitor->is_flush = 1; - flush_monitor->starting_id = config.monitor_start_counter; - check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, sizeof(struct sling_message_monitor_flush), flush_monitor, 1, false)); + char out[recv_size + sizeof(struct sling_message_monitor)]; + struct sling_message_monitor *to_send = (struct sling_message_monitor *) out; + to_send->message_counter = config.message_counter++; + to_send->is_flush = 0; + strcpy(to_send->string, buffer); - line_count = 0; + send_hello_if_zero(); + check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, recv_size + sizeof(struct sling_message_monitor), to_send, 1, false)); } + fclose(fp); + } + + if (config.monitor_start_counter != config.message_counter) { // Some lines have been sent + char out[sizeof(struct sling_message_monitor_flush)]; + struct sling_message_monitor_flush *flush_monitor = (struct sling_message_monitor_flush *) out; + flush_monitor->message_counter = config.message_counter++; + flush_monitor->is_flush = 1; + flush_monitor->starting_id = config.monitor_start_counter; + check_mosq(mosquitto_publish(mosq, NULL, config.outtopic_monitor, sizeof(struct sling_message_monitor_flush), flush_monitor, 1, false)); } - pclose(fp); } static int main_loop(void) { @@ -352,7 +388,7 @@ static int main_loop(void) { main_loop_epoll_add(main_loop_epoll_child, sigchldfd); while (1) { - get_peripherals(); // + get_peripherals(); int nfds = check_posix(epoll_wait(config.epollfd, events, max_events, 1000), "epoll_wait"); for (int n = 0; n < nfds; ++n) { struct epoll_event *ev = events + n;