commit 8ab81f735e350bd9c81fcd467720389ff33fae73 Author: Dirk Jahnke Date: Fri Apr 6 14:39:59 2018 +0200 Initial version (test / feasibility on esp32 and esp8266) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dbe9166 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vscode +build +*.tmp +*.bak diff --git a/README.md b/README.md new file mode 100644 index 0000000..1b34d6d --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Thermo Printer Interface / Remote Control + +## Overview + +This is about a device that can be called by WLAN / TCP/IP and prints on a cheap thermo printer using paper rolls. + +Hardware used: +- ESP-CPU: + -- Wemos ESP32 LoLin (any ESP32 should work), we are using UART1 (GPIO26=Tx) + -- Wemos ESP8266 (any should work), we are using UART1 Tx only (GPIO2=Tx) +- GOOJPRT QR204 Micro Embedded Printer with RS232/TTL and USB-Interface + -- TX, RX, GND connected to ESP32 + -- POWER connected to seperate power supply (+5V/GND) + + +## How to install this app + +- Install and start [mos tool](https://mongoose-os.com/software.html) +- Switch to the Project page, find and import this app, build and flash it: + +

+ +

diff --git a/fs/index.html b/fs/index.html new file mode 100644 index 0000000..5f37107 --- /dev/null +++ b/fs/index.html @@ -0,0 +1,5 @@ + + +

Welcome to the empty project

+ + diff --git a/mos.yml b/mos.yml new file mode 100644 index 0000000..176659b --- /dev/null +++ b/mos.yml @@ -0,0 +1,90 @@ +author: Dirk Jahnke +description: Thermo Printer Remote Controller +version: 1.0 + +libs_version: ${mos.version} +modules_version: ${mos.version} +mongoose_os_version: ${mos.version} +# platform: esp8266 +# platform: esp32 + +# Optional. List of tags for online search. +tags: + - c + +# List of files / directories with C sources. No slashes at the end of dir names. +sources: + - src + +# List of dirs. Files from these dirs will be copied to the device filesystem +filesystem: + - fs + +# Custom configuration entries, settable via "device configuration" +# Below is a custom firmware configuration example. +# Uncomment and modify according to your needs: + +config_schema: +# - ["my_app", "o", {title: "My app custom settings"}] +# - ["my_app.bool_value", "b", false, {title: "Some boolean value"}] +# - ["my_app.string_value", "s", "", {title: "Some string value"}] +# - ["my_app.int_value", "i", 123, {title: "Some integer value"}] + - ["i2c.enable", true] + - ["i2c.freq", 400] + - ["i2c.sda_gpio", 4] # D2 + - ["i2c.scl_gpio", 5] # D1 + - ["flashLight", "o", {title: "Flash light / alarm light settings"}] + - ["flashLight.address", "i", 0x30, {title: "i2c address of motor controller TB6612 (e.g. WEMOS)"}] + - ["flashLight.motorFrequency", "i", 500, {title: "Frequency of PWM in Hz"}] + - ["flashLight.motorUpdateTime", "i", 50, {title: "Time between motor updates in msec"}] + - ["flashLight.mqttCtrlTopic", "s", "flashLight/%s/ctrl", {title: "MQTT channel to subscribe to receive commands; %s is replaced by clientId"}] + - ["flashLight.mqttStatusTopic", "s", "flashLight/%s/status", {title: "MQTT channel to publish to send status change infos; %s is replaced by clientId"}] + - ["mqtt.enable", true] + - ["mqtt.server", "mqtt.pmpark.de:1883"] + - ["mqtt.user", "default"] + - ["mqtt.pass", "12345678"] + - ["mqtt.will_message", "offline"] + - ["mqtt.will_topic", "flashLight/"] + + - ["sntp.enable", true] + - ["sntp.server", "time.google.com"] + + +# These settings get compiled into the C structure, and can be accessed +# from the C code this way: +# +# printf("Hello from %s!\n", mgos_sys_config_get_device_id()); +# +# Settings are cool: can be modified remotely without full firmware upgrade! +# +# To see all available compiled settings, buid the firmware and open +# build/gen/mgos_config.h file. +# +# Also, in this config_schema section, you can override existing +# settings that has been created by other libraries. For example, debug log +# level is 2 by default. For this firmware we can override it to 3: +# +# config_schema: +# - ["debug.level", 3] + + +# List of libraries used by this app, in order of initialisation +libs: + - origin: https://github.com/mongoose-os-libs/ca-bundle + - origin: https://github.com/mongoose-os-libs/i2c + - origin: https://github.com/mongoose-os-libs/rpc-service-config + - origin: https://github.com/mongoose-os-libs/rpc-service-fs + - origin: https://github.com/mongoose-os-libs/rpc-uart + - origin: https://github.com/mongoose-os-libs/spi + - origin: https://github.com/mongoose-os-libs/wifi + - origin: https://github.com/mongoose-os-libs/http-server + - origin: https://github.com/mongoose-os-libs/rpc-loopback + - origin: https://github.com/mongoose-os-libs/rpc-mqtt + - origin: https://github.com/mongoose-os-libs/rpc-service-ota + - origin: https://github.com/mongoose-os-libs/rpc-service-cron + - origin: https://github.com/mongoose-os-libs/crontab + - origin: https://github.com/mongoose-os-libs/dash + - origin: https://github.com/mongoose-os-libs/sntp + +# Used by the mos tool to catch mos binaries incompatible with this file format +manifest_version: 2017-05-18 diff --git a/src/QR204.c b/src/QR204.c new file mode 100644 index 0000000..eb7eb07 --- /dev/null +++ b/src/QR204.c @@ -0,0 +1,72 @@ +#include "QR204.h" + +static bool initialized = false; +static uint8_t uart = 0; + +static const char initCmd[] = { 0x1b, '@' }; + +// ***** INIT ***** +void tp_init(uint8_t uartNo) { + if (!initialized) { + uart = uartNo; + mgos_uart_write(uart, initCmd, sizeof(initCmd)); + initialized = true; + } +} +// ***** End of INIT ***** + +// ***** MODE Handling ***** +static uint8_t currentMode = 0; + +void tp_set_mode(uint8_t addModes) { + currentMode |= addModes; + char setModeCmd[3] = {0x1b, '!', currentMode}; + mgos_uart_write(uart, setModeCmd, 3); +} + +void tp_reset_mode(uint8_t removeModes) { + currentMode &= ~removeModes; + char setModeCmd[3] = {0x1b, '!', currentMode}; + mgos_uart_write(uart, setModeCmd, 3); +} + +void tp_reverse_feed(uint8_t numLines) { + char cmd[3] = { 0x1b, 'e', numLines }; + mgos_uart_write(uart, cmd, 3); +} + +void tp_linefeed(uint8_t numLines) { + char cmd[3] = { 0x1b, 'd', numLines }; + mgos_uart_write(uart, cmd, 3); +} + +void tp_cutpaper(bool fullcut) { + char cmd[3] = { 0x1d, 'V', fullcut ? '0' : '1' }; + mgos_uart_write(uart, cmd, 3); +} + +// ***** End of MODE Handling ***** + +/* +PRINT #1, CHR$(&H1B);"@"; 'Initializes the printer (ESC @) +PRINT #1, CHR$(&H1B);"a";CHR$(1);'Specifies a centered printing position (ESC a) +PRINT #1, CHR$(&H1B);"!";CHR$(0); 'Specifies font A (ESC !) +PRINT #1, "January 14, 2002 15:00"; +PRINT #1, CHR$(&H1B);"d";CHR$(3); 'Prints and 3 line feeding (ESC d) +PRINT #1, CHR$(&H1B);"a";CHR$(0); 'Selects the left print position (ESC a) +PRINT #1, CHR$(&H1B);"!";CHR$(1); 'Selects font B +PRINT #1, "TM-U210B" +PRINT #1, "TM-U210D" +PRINT #1, "PS-170" +PRINT #1, CHR$(&HA); +$20.00";CHR$(&HA); $21.00";CHR$(&HA); $17.00";CHR$(&HA); +'Line feeding (LF) +PRINT #1, CHR$(&H1B);"!";CHR$(17); 'Selects double-height mode +PRINT #1, "TOTAL $58.00"; CHR$(&HA); +PRINT #1, CHR$(&H1B);"!";CHR$(0); 'Cancels double-height mode +PRINT #1, "------------------------------";CHR$(&HA); PRINT #1, "PAID $60.00";CHR$(&HA); PRINT #1, "CHANGE $ 2.00";CHR$(&HA); +PRINT #1, CHR$(&H1D);"V";CHR$(66);CHR$(0); 'Feeds paper & cut +’Drawer Kick (ESC p) +PRINT #1, CHR$(&H1B); CHR$(&H70); CHR$(&H0); CHR$(60); CHR$(120); + +*/ \ No newline at end of file diff --git a/src/QR204.h b/src/QR204.h new file mode 100644 index 0000000..6aac5db --- /dev/null +++ b/src/QR204.h @@ -0,0 +1,25 @@ + +#ifndef __QR204_H +#define __QR204_H + +#include "mgos.h" +#include "mgos_system.h" +#include "mgos_uart.h" + + +#define TP_MODE_ALTERNATEFONT 0x01 +#define TP_MODE_EMPFHASIZED 0x08 +#define TP_MODE_DOUBLEHEIGHT 0x10 +#define TP_MODE_DOUBLEWIDTH 0x20 +#define TP_MODE_UNDERLINED 0x80 +#define TP_MODE_ALL 0xff + +#define tp_print mgos_uart_printf + +extern void tp_init(uint8_t uartNo); +extern void tp_set_mode(uint8_t addModes); +extern void tp_reset_mode(uint8_t removeModes); +extern void tp_reverse_feed(uint8_t numLines); +extern void tp_linefeed(uint8_t numLines); +#endif + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..21662c3 --- /dev/null +++ b/src/main.c @@ -0,0 +1,500 @@ +#include + +#include "mgos.h" +#include "mgos_app.h" +#include "mgos_gpio.h" +#include "mgos_system.h" +#include "mgos_timers.h" +#include "mgos_uart.h" +#include "mgos_rpc.h" +#include "mgos_sys_config.h" +#include "mgos_mqtt.h" +#include "mgos_net.h" +#include "mgos_crontab.h" +#include "common/mbuf.h" +#include "common/platform.h" +#include "common/cs_dbg.h" +#include "common/json_utils.h" +#include "common/mg_str.h" +#include "common/str_util.h" +#if CS_PLATFORM == CS_P_ESP32 + #include +#endif + +#include "QR204.h" + +static bool doPrint = false; + +#if CS_PLATFORM == CS_P_ESP32 + #define UART_NO 1 + int esp32_uart_rx_fifo_len(int uart_no); + extern uint8_t temprature_sens_read(); + extern uint32_t hall_sens_read(); + static int tempOffset = 17; +#elif CS_PLATFORM == CS_P_ESP8266 + #define UART_NO 1 +#else + #error Unsupported platform +#endif + +static void timer_cb(void *arg) { + /* + * Note: do not use mgos_uart_write to output to console UART (0 in our case). + * It will work, but output may be scrambled by console debug output. + */ + printf("Timer loop!\n"); + + if (doPrint) { + tp_reset_mode(TP_MODE_ALL); + tp_print(UART_NO, "Timer loop!\n"); + tp_set_mode(TP_MODE_UNDERLINED); + tp_print(UART_NO, "0,123456789\n"); + } + /* tp_print(UART_NO, "- -\n"); + tp_print(UART_NO, " - - \n"); + tp_reverse_feed(2); + tp_print(UART_NO, " - - \n"); + tp_print(UART_NO, "- -\n");*/ + + +#if CS_PLATFORM == CS_P_ESP32 + uint32_t hall = hall_sens_read(); + uint8_t temp = temprature_sens_read(); + esp_chip_info_t ci; + esp_chip_info(&ci); + tp_print(UART_NO, "t=%.1f C, h=%ld mH, tasks=%d\n", (float) (temp-32)/1.8 - tempOffset, hall, uxTaskGetNumberOfTasks()); +#elif CS_PLATFORM == CS_P_ESP8266 + tp_print(UART_NO, "xyz\n"); +#endif + + (void) arg; +} + +static void printSystemInfo() { + #if CS_PLATFORM == CS_P_ESP32 + esp_chip_info_t ci; + esp_chip_info(&ci); + tp_print(UART_NO, + "ESP32 mod=%d, cores=%d, rev=%d\n", + ci.model, ci.cores, ci.revision); + #elif CS_PLATFORM == CS_P_ESP8266 + tp_print(UART_NO, + "ESP8266: cpu=%d MHz\n", + (int) mgos_get_cpu_freq() / 1000000); + tp_print(UART_NO, + "mem=%d kB, free=%d kB, fs=%d kB\n", + (int) mgos_get_heap_size()/1024, + (int) mgos_get_free_heap_size()/1024, + (int) mgos_get_fs_size()/1024); + #endif +} + +enum mgos_app_init_result mgos_app_init(void) { + struct mgos_uart_config ucfg; + mgos_uart_config_set_defaults(UART_NO, &ucfg); + /* + * At this point it is possible to adjust baud rate, pins and other settings. + * 115200 8-N-1 is the default mode, but we set it anyway + */ + ucfg.baud_rate = 9600; + ucfg.num_data_bits = 8; + ucfg.parity = MGOS_UART_PARITY_NONE; + ucfg.stop_bits = MGOS_UART_STOP_BITS_1; + if (!mgos_uart_configure(UART_NO, &ucfg)) { + LOG(LL_ERROR,("ERROR: Cannot configure uart %d", UART_NO)); + return MGOS_APP_INIT_ERROR; + } + + printf("Initial printer operation"); + tp_init(UART_NO); + mgos_set_timer(60000 /* ms */, true /* repeat */, timer_cb, NULL /* arg */); + + mgos_uart_set_rx_enabled(UART_NO, false); + + tp_reset_mode(TP_MODE_ALL); + tp_print(UART_NO, "TEST Print\r"); + tp_print(UART_NO, "----------\n"); + printSystemInfo(); + + return MGOS_APP_INIT_SUCCESS; +} + +/* -------------------------------------------------------------------- */ + +/* ======================================= + +static void recalcTimings() { + flashLightRampUp_deltaSpeed = (flashLightSpeed * motorUpdateTime_msec) / motorRampUpTime_msec; + flashLightRampDown_deltaSpeed = (flashLightSpeed * motorUpdateTime_msec) / motorRampDownTime_msec; +} + +static void pubStatus(const char *statusString, double percentage) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + if (!mqttConnected) return; + + mbuf_init(&fb, 30); + if (mgos_mqtt_global_connect()) { + json_printf(&out, "{statusString: %Q, speed: %f}", statusString, percentage); + mgos_mqtt_pub(pubStatusTopic, fb.buf, fb.len, 0, true); + } + +} + +static void motor_timer_cb(void *arg) { + static bool stopped = false; + + switch (motorStatus) { + case MotorStatus_Off: + wemos_motor_stop(M1); + break; + case MotorStatus_On: + wemos_motor_setmotor(M1, motorDirection, pwm); + break; + case MotorStatus_RampUp: + pwm += flashLightRampUp_deltaSpeed; + if (pwm >= flashLightSpeed) { + LOG(LL_INFO, ("MotorStatus_RampUp: Speed target reached")); + pwm = flashLightSpeed; + motorStatus = MotorStatus_On; + } + wemos_motor_setmotor(M1, motorDirection, pwm); + // LOG(LL_INFO, ("M1, dir=%d, pwm=%f", motorDirection, pwm)); + break; + case MotorStatus_RampDown: + pwm -= flashLightRampDown_deltaSpeed; + if (pwm <= flashLightTargetSpeed) { + if (pwm <= 0.0) { + motorStatus = MotorStatus_Off; + pwm = 0.0; + wemos_motor_stop(M1); + // change direction for next time, when motor turns on again + if (motorDirection == _CW) { + motorDirection = _CCW; + } else { + motorDirection = _CW; + } + } else { + pwm = flashLightTargetSpeed; + LOG(LL_INFO, ("MotorStatus_RampDown: Speed target reached")); + motorStatus = MotorStatus_On; + wemos_motor_setmotor(M1, motorDirection, pwm); + } + } else { + wemos_motor_setmotor(M1, motorDirection, pwm); + // LOG(LL_INFO, ("M1, dir=%d, pwm=%f", motorDirection, pwm)); + } + break; + case MotorStatus_DemoMode: + default: + if (pwm > flashLightSpeed + 5.0) { + pwm = 0.0; // start again + stopped = false; + } else { + pwm += 0.1; + if (!stopped) { + wemos_motor_setmotor(M1, motorDirection, pwm); + LOG(LL_INFO, ("M1, dir=%d, pwm=%f", motorDirection, pwm)); + pubStatus("on", pwm); + + if (pwm > flashLightSpeed) { + // wemos_motor_setmotor(M1, _STOP, 0.0); + wemos_motor_setmotor(M1, _STANDBY, pwm); + stopped = true; + LOG(LL_INFO, ("Stopped/Standby")); + pubStatus("off", 0); + } + } + } + break; + } + (void) arg; +} + +static void flashLightOn() { + LOG(LL_INFO, ("FlashLight ON\n")); + flashLightTargetSpeed = flashLightSpeed; + motorStatus = MotorStatus_RampUp; // this starts the motor on next timer callback + pubStatus("on", flashLightSpeed); +} + +static void rpc_flashLightOn(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + flashLightOn(); + mbuf_init(&fb, 100); + json_printf(&out, "{result: 0, resultString: %Q}", "OK"); + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + + (void) cb_arg; + (void) fi; + (void) args; +} + +static void cron_flashLightOn(struct mg_str action, struct mg_str payload, void *userdata) { + LOG(LL_INFO, ("Crontab flashLightOn fired")); + flashLightOn(); + (void) action; + (void) payload; + (void) userdata; +} + +static void flashLightOff() { + LOG(LL_INFO, ("FlashLight OFF\n")); + flashLightTargetSpeed = 0.0; + motorStatus = MotorStatus_RampDown; // this stops the motor on next timer callback + pubStatus("off", 0); +} + +static void rpc_flashLightOff(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + flashLightOff(); + mbuf_init(&fb, 100); + json_printf(&out, "{result: 0, resultString: %Q}", "OK"); + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + + (void) cb_arg; + (void) fi; + (void) args; +} + +static void cron_flashLightOff(struct mg_str action, struct mg_str payload, void *userdata) { + LOG(LL_INFO, ("Crontab flashLightOff fired")); + flashLightOff(); + (void) action; + (void) payload; + (void) userdata; +} + +static void cron_init() { + mgos_crontab_register_handler(mg_mk_str("FlashLightOn"), cron_flashLightOn, NULL); + mgos_crontab_register_handler(mg_mk_str("FlashLightOff"), cron_flashLightOff, NULL); +} + +static void flashLightSetSpeed(uint16_t newSpeed) { + flashLightTargetSpeed = (double) newSpeed; + flashLightSpeed = flashLightTargetSpeed; + if (pwm < flashLightTargetSpeed) { + motorStatus = MotorStatus_RampUp; + } else if (pwm > flashLightTargetSpeed) { + motorStatus = MotorStatus_RampDown; + } +} + +static void rpc_flashLightSetSpeed(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + mbuf_init(&fb, 100); + + int speed = 0; + + if (json_scanf(args.p, args.len, ri->args_fmt, &speed) == 1) { + printf("FlashLight set speed to %d\n", speed); + json_printf(&out, "{result: 0, resultString: %Q, speed: %d}", "OK", speed); + flashLightSetSpeed(speed); + } else { + json_printf(&out, "{error: %Q}", "speed is required"); + } + + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + recalcTimings(); + + (void) cb_arg; + (void) fi; + (void) args; +} + +static void flashLightSetRampupTime(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + mbuf_init(&fb, 100); + + uint16_t rampUpTime_msec = 0; + + if (json_scanf(args.p, args.len, ri->args_fmt, &rampUpTime_msec) == 1) { + motorRampUpTime_msec = rampUpTime_msec; + printf("FlashLight set motor ramp up time to %d\n", rampUpTime_msec); + json_printf(&out, "{result: 0, resultString: %Q, rampUpTime_ms: %d}", "OK", rampUpTime_msec); + } else { + json_printf(&out, "{error: %Q}", "rampUpTime_msec is required"); + } + + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + recalcTimings(); + + (void) cb_arg; + (void) fi; + (void) args; +} + +static void flashLightSetRampdownTime(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + mbuf_init(&fb, 100); + + uint16_t rampDownTime_msec = 0; + + if (json_scanf(args.p, args.len, ri->args_fmt, &rampDownTime_msec) == 1) { + motorRampDownTime_msec = rampDownTime_msec; + printf("FlashLight set motor ramp up time to %d\n", rampDownTime_msec); + json_printf(&out, "{result: 0, resultString: %Q, rampDownTime_ms: %d}", "OK", rampDownTime_msec); + } else { + json_printf(&out, "{error: %Q}", "rampDownTime_msec is required"); + } + + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + recalcTimings(); + + (void) cb_arg; + (void) fi; + (void) args; +} + +static void flashLightSetMotorUpdateTime(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + mbuf_init(&fb, 100); + + uint16_t updateTime = 0; + + if (json_scanf(args.p, args.len, ri->args_fmt, &updateTime) == 1) { + motorUpdateTime_msec = updateTime; + printf("FlashLight set updateTime_msec tp %d\n", updateTime); + json_printf(&out, "{result: 0, resultString: %Q, udateTime_ms: %d}", "OK", updateTime); + } else { + json_printf(&out, "{error: %Q}", "motorUpdateTime_msec is required"); + } + + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + recalcTimings(); + + (void) cb_arg; + (void) fi; + (void) args; +} + +static void flashLightGetSettings(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + mbuf_init(&fb, 1024); + + json_printf(&out, "{pwm: %f, speed: %f, rampupTime_ms: %d, rampdownTime_ms: %d, updateTime_ms: %d, rampupDeltaSpeed: %f, rampdownDeltaSpeed: %f, motorDirection: %d, clientId: %Q, commandTopic: %Q, statusTopic: %Q, mqttConnected: %Q, motorStatus: %d}", + pwm, flashLightSpeed, motorRampUpTime_msec, motorRampDownTime_msec, motorUpdateTime_msec, flashLightRampUp_deltaSpeed, flashLightRampDown_deltaSpeed, + motorDirection, clientId, commandTopic, pubStatusTopic, mqttConnected ? "true" : "false", motorStatus); + + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + + (void) cb_arg; + (void) fi; + (void) args; +} + +void net_changed(int ev, void *evd, void *arg) { + if (ev != MGOS_NET_EV_IP_ACQUIRED) return; + // call_peer(); + (void) evd; + (void) arg; +} + +static void mqttCommandHandler(struct mg_connection *c, const char *topic, int topic_len, + const char *msg, int msg_len, void *userdata) { + LOG(LL_INFO, ("Got message on topic %.*s", topic_len, topic)); + + (void) c; + (void) topic; + (void) topic_len; + (void) msg; + (void) msg_len; + (void) userdata; +} + +// void onMqttConnection(struct mg_connection *c, const char *client_id, struct mg_send_mqtt_handshake_opts *opts, void *fn_arg) { +void onMqttConnection(struct mg_connection *c, const char *client_id, struct mg_send_mqtt_handshake_opts *opts, void *fn_arg) { + // add MQTT cmd subscription + LOG(LL_INFO, ("onMqttConnection handler called with clientId=%s", client_id)); + #if 0 + #endif + mgos_mqtt_sub(commandTopic, mqttCommandHandler, NULL); + mqttConnected = true; + + (void) c; + (void) client_id; + (void) opts; + (void) fn_arg; +} + +enum mgos_app_init_result mgos_app_init(void) { + struct mg_rpc *c = mgos_rpc_get_global(); + mg_rpc_add_handler(c, "FlashLight.On", NULL, rpc_flashLightOn, NULL); + mg_rpc_add_handler(c, "FlashLight.Off", NULL, rpc_flashLightOff, NULL); + mg_rpc_add_handler(c, "FlashLight.Speed", "{speed: %d}", rpc_flashLightSetSpeed, NULL); + mg_rpc_add_handler(c, "FlashLight.RampUpTime_msec", "{rampUpTime_ms: %d}", flashLightSetRampupTime, NULL); + mg_rpc_add_handler(c, "FlashLight.RampDownTime_msec", "{rampDownTime_ms: %d}", flashLightSetRampdownTime, NULL); + mg_rpc_add_handler(c, "FlashLight.MotorUpdateTime_msec", "{uptdateTime_ms: %d}", flashLightSetMotorUpdateTime, NULL); + mg_rpc_add_handler(c, "FlashLight.GetSettings", NULL, flashLightGetSettings, NULL); + mgos_event_add_group_handler(MGOS_EVENT_GRP_NET, net_changed, NULL); + + // enable crontab + cron_init(); + + // add MQTT cmd subscription + LOG(LL_INFO, ("Initializing MQTT")); + clientId = mgos_sys_config_get_mqtt_client_id(); + clientId = clientId ? clientId : mgos_sys_config_get_device_id(); + LOG(LL_INFO, ("clientId=%s", clientId)); + LOG(LL_INFO, ("cmdTopic=%s", mgos_sys_config_get_flashLight_mqttCtrlTopic())); + LOG(LL_INFO, ("pubStatusTopic=%s", mgos_sys_config_get_flashLight_mqttStatusTopic())); + c_snprintf(commandTopic, sizeof(commandTopic), mgos_sys_config_get_flashLight_mqttCtrlTopic(), clientId); + c_snprintf(pubStatusTopic, sizeof(pubStatusTopic), mgos_sys_config_get_flashLight_mqttStatusTopic(), clientId); + LOG(LL_INFO, ("cmdTopic=%s", commandTopic)); + LOG(LL_INFO, ("pubStatusTopic=%s", pubStatusTopic)); + mgos_mqtt_set_connect_fn(onMqttConnection, NULL); + + motorFrequency = mgos_sys_config_get_flashLight_motorFrequency(); + LOG(LL_INFO, ("motorFrequency=%d Hz", motorFrequency)); + motorAddress = mgos_sys_config_get_flashLight_address(); + LOG(LL_INFO, ("motorAddress=%d", motorAddress)); + LOG(LL_INFO, ("Initializing motor controller")); + recalcTimings(); + wemos_motor_init(); + LOG(LL_INFO, ("Initializing motor M1")); + wemos_motor_initMotor(M1, motorAddress, motorFrequency); + LOG(LL_INFO, ("Setting up timer")); + motorUpdateTime_msec = mgos_sys_config_get_flashLight_motorUpdateTime(); + mgos_set_timer(motorUpdateTime_msec, MGOS_TIMER_REPEAT, motor_timer_cb, NULL); + LOG(LL_INFO, ("Initialization done")); + return MGOS_APP_INIT_SUCCESS; +} + + ======================================= */ + \ No newline at end of file