merge max72xx clock progress and i2c pinwide scanner and misc fixes

* MAX72XX

* better

* faster buof

* eext

* test

* fx

* fxes

* tr

* fx

* Update drv_max72xx_clock.c

* fxes

* test

* fxes

* tests fxes

* fxes

* scr

* fx

* Update drv_local.h

* show

* Update drv_max72xx_clock.c

* test

* Delete lastEnumTemplate.txt

* TEST

* scan

* Update drv_main.c

* Update obk_main.cmake

* Update drv_multiPinI2CScanner.c

* dbg

* fxes

* Update drv_multiPinI2CScanner.c

* Update drv_multiPinI2CScanner.c

* Update drv_multiPinI2CScanner.c

* owm

* osm test

* restorew platfotms

* Update selftest_openWeatherMap.c

* test

* getter

* Update obk_config.h
This commit is contained in:
openshwprojects
2025-11-11 16:27:13 +01:00
committed by GitHub
parent f58a25fc3d
commit f2c87bf690
24 changed files with 841 additions and 262 deletions

View File

@@ -1,7 +0,0 @@
{ 17822728f value == '1' }
Ok
{ 2.121830e-304lif value == '0' }
Bad
{-9.255963e+61lse }
Unknown
{-9.255963e+61ndif }

View File

@@ -242,6 +242,7 @@
<ClCompile Include="src\driver\drv_max72xx_internal.c" />
<ClCompile Include="src\driver\drv_max72xx_single.c" />
<ClCompile Include="src\driver\drv_mcp9808.c" />
<ClCompile Include="src\driver\drv_multiPinI2CScanner.c" />
<ClCompile Include="src\driver\drv_ntp.c" />
<ClCompile Include="src\driver\drv_ntp_events.c" />
<ClCompile Include="src\driver\drv_openWeatherMap.c" />
@@ -791,8 +792,10 @@
<ClCompile Include="src\selftest\selftest_http_led.c" />
<ClCompile Include="src\selftest\selftest_if_inside_backlog.c" />
<ClCompile Include="src\selftest\selftest_json_lib.c" />
<ClCompile Include="src\selftest\selftest_max72xx.c" />
<ClCompile Include="src\selftest\selftest_mqtt_get.c" />
<ClCompile Include="src\selftest\selftest_ntp_sunsetSunrise.c" />
<ClCompile Include="src\selftest\selftest_openWeatherMap.c" />
<ClCompile Include="src\selftest\selftest_pir.c" />
<ClCompile Include="src\selftest\selftest_role_toggleAll_2.c" />
<ClCompile Include="src\selftest\selftest_cfg_via_http.c" />

View File

@@ -414,6 +414,9 @@
<ClCompile Include="src\driver\drv_ddpSend.c" />
<ClCompile Include="src\cmnds\cmd_enums.c" />
<ClCompile Include="src\driver\drv_bkPartitions.c" />
<ClCompile Include="src\selftest\selftest_max72xx.c" />
<ClCompile Include="src\driver\drv_multiPinI2CScanner.c" />
<ClCompile Include="src\selftest\selftest_openWeatherMap.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\base64\base64.h" />

View File

@@ -97,6 +97,7 @@ set(OBKM_SRC
${OBK_SRCS}driver/drv_max72xx_internal.c
${OBK_SRCS}driver/drv_max72xx_single.c
${OBK_SRCS}driver/drv_mcp9808.c
${OBK_SRCS}driver/drv_multiPinI2CScanner.c
${OBK_SRCS}driver/drv_ntp.c
${OBK_SRCS}driver/drv_ntp_events.c
${OBK_SRCS}driver/drv_openWeatherMap.c

View File

@@ -117,6 +117,7 @@ OBKM_SRC += $(OBK_SRCS)driver/drv_max72xx_clock.c
OBKM_SRC += $(OBK_SRCS)driver/drv_max72xx_internal.c
OBKM_SRC += $(OBK_SRCS)driver/drv_max72xx_single.c
OBKM_SRC += $(OBK_SRCS)driver/drv_mcp9808.c
OBKM_SRC += $(OBK_SRCS)driver/drv_multiPinI2CScanner.c
OBKM_SRC += $(OBK_SRCS)driver/drv_ntp.c
OBKM_SRC += $(OBK_SRCS)driver/drv_ntp_events.c
OBKM_SRC += $(OBK_SRCS)driver/drv_openWeatherMap.c

View File

@@ -132,7 +132,7 @@ void DRV_DDPSend_Shutdown()
}
g_queue = 0;
}
void DRV_DDPSend_AppendInformationToHTTPIndexPage(http_request_t* request)
void DRV_DDPSend_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState)
{
hprintf255(request, "<h2>DDP sent: %i packets, %i bytes, errored packets: %i</h2>",
stat_sendPackets, stat_sendBytes, stat_failedPackets);

View File

@@ -61,6 +61,9 @@ void DRV_GosundSW2_RunFrame();
void DRV_PinMutex_Init();
void DRV_PinMutex_RunFrame();
void MultiPinI2CScanner_Init();
void MultiPinI2CScanner_RunFrame();
void MultiPinI2CScanner_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState);
void SM16703P_Init();
void SM16703P_Shutdown();
@@ -167,6 +170,9 @@ void PIR_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState
void TMGN_RunQuickTick();
void DRV_MAX72XX_Init();
void DRV_MAX72XX_Shutdown();
int MAX72XXSingle_CountPixels(bool bOn);
int MAX72XXSingle_GetScrollCount();
void apply_smart_light();
@@ -234,7 +240,7 @@ void TCL_DoDiscovery(const char *topic);
void DRV_DDPSend_Init();
void DRV_DDPSend_Shutdown();
void DRV_DDPSend_RunFrame();
void DRV_DDPSend_AppendInformationToHTTPIndexPage(http_request_t* request);
void DRV_DDPSend_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState);
void TXW_Cam_Init(void);
void TXW_Cam_RunEverySecond(void);

View File

@@ -195,6 +195,13 @@ static driver_t g_drivers[] = {
//drvdetail:"requires":""}
{ "Test", Test_Init, NULL, Test_AppendInformationToHTTPIndexPage, Test_RunQuickTick, NULL, NULL, NULL, false },
#endif
#if ENABLE_MULTIPINI2CSCANNER
//drvdetail:{"name":"MultiPinI2CScanner",
//drvdetail:"title":"TODO",
//drvdetail:"descr":"qq.",
//drvdetail:"requires":""}
{ "MultiPinI2CScanner", MultiPinI2CScanner_Init, NULL, MultiPinI2CScanner_AppendInformationToHTTPIndexPage, MultiPinI2CScanner_RunFrame, NULL, NULL, NULL, false },
#endif
#if ENABLE_I2C
//drvdetail:{"name":"I2C",
//drvdetail:"title":"TODO",
@@ -431,7 +438,7 @@ static driver_t g_drivers[] = {
//drvdetail:"title":"TODO",
//drvdetail:"descr":"MAX72XX LED matrix display driver with font and simple script interface. See [protocol explanation](https://www.elektroda.pl/rtvforum/viewtopic.php?p=18040628#18040628)",
//drvdetail:"requires":""}
{ "MAX72XX", DRV_MAX72XX_Init, NULL, NULL, NULL, NULL, NULL, NULL, false },
{ "MAX72XX", DRV_MAX72XX_Init, NULL, NULL, NULL, DRV_MAX72XX_Shutdown, NULL, NULL, false },
#endif
#if ENABLE_DRIVER_BMPI2C
//drvdetail:{"name":"BMPI2C",

View File

@@ -29,40 +29,6 @@ enum {
CLOCK_HUMIDITY,
CLOCK_TEMPERATURE,
};
bool CHANNEL_IsHumidity(int type) {
if (type == ChType_Humidity)
return true;
if (type == ChType_Humidity_div10)
return true;
return false;
}
bool CHANNEL_IsTemperature(int type) {
if (type == ChType_Temperature)
return true;
if (type == ChType_Temperature_div10)
return true;
if (type == ChType_Temperature_div100)
return true;
return false;
}
bool CHANNEL_GetGenericOfType(float *out, bool (*checker)(int type)) {
int i, t;
for (i = 0; i < CHANNEL_MAX; i++) {
t = g_cfg.pins.channelTypes[i];
if (checker(t)) {
*out = CHANNEL_GetFinalValue(i);
return true;
}
}
return false;
}
bool CHANNEL_GetGenericHumidity(float *out) {
return CHANNEL_GetGenericOfType(out, CHANNEL_IsHumidity);
}
bool CHANNEL_GetGenericTemperature(float *out) {
return CHANNEL_GetGenericOfType(out, CHANNEL_IsTemperature);
}
void Clock_Send(int type) {
char time[64];
struct tm *ltm;
@@ -94,11 +60,17 @@ void Clock_Send(int type) {
strcat(p, " ");
}
else if (type == CLOCK_HUMIDITY) {
CHANNEL_GetGenericHumidity(&val);
if (false==CHANNEL_GetGenericHumidity(&val)) {
// failed - exit early, do not change string
return;
}
sprintf(time, "H: %i%% ", (int)val);
}
else if (type == CLOCK_TEMPERATURE) {
CHANNEL_GetGenericTemperature(&val);
if (false == CHANNEL_GetGenericTemperature(&val)) {
// failed - exit early, do not change string
return;
}
sprintf(time, "T: %iC ", (int)val);
}
@@ -116,12 +88,9 @@ void Clock_SendHumidity() {
void Clock_SendTemperature() {
Clock_Send(CLOCK_TEMPERATURE);
}
static int cycle = 0;
static unsigned int cycle = 0;
void Run_NoAnimation() {
//int max_cycle;
//bool bHasDHT;
cycle+=4;
if (cycle < 10) {
Clock_SendDate();
@@ -135,9 +104,15 @@ void Run_NoAnimation() {
else {
Clock_SendTemperature();
}
CMD_ExecuteCommandArgs("MAX72XX_Show", "", 0);
cycle %= 40;
}
void Run_Animated() {
cycle++;
if (cycle < 4) {
return;
}
cycle = 0;
char time[64];
struct tm *ltm;
char *p;
@@ -148,10 +123,12 @@ void Run_Animated() {
if (ltm == 0) {
return;
}
int scroll = MAX72XXSingle_GetScrollCount();
//scroll_cycle = 0;
if (ltm->tm_sec == 0) {
if (scroll == 0) {
time[0] = 0;
p = time;
p = my_strcat(p, " ");
p = add_padded(p, ltm->tm_hour);
p = my_strcat(p, ":");
@@ -159,29 +136,33 @@ void Run_Animated() {
strcat(p, " ");
p = my_strcat(p, " ");
p = add_padded(p, ltm->tm_year);
p = add_padded(p, ltm->tm_year+1900);
p = my_strcat(p, ".");
p = add_padded(p, ltm->tm_mon + 1);
p = my_strcat(p, ".");
p = add_padded(p, ltm->tm_mday);
strcat(p, "");
strcat(p, " ");
CMD_ExecuteCommandArgs("MAX72XX_Clear", NULL, 0);
CMD_ExecuteCommandArgs("MAX72XX_Print", time, 0);
}
else {
CMD_ExecuteCommandArgs("MAX72XX_Scroll", "1", 0);
CMD_ExecuteCommandArgs("MAX72XX_Scroll", "-1", 0);
CMD_ExecuteCommandArgs("MAX72XX_Show", "", 0);
}
bool g_animated = false;
void DRV_MAX72XX_Clock_OnEverySecond() {
if (g_animated == false) {
Run_NoAnimation();
}
}
void DRV_MAX72XX_Clock_OnEverySecond() {
Run_NoAnimation();
}
void DRV_MAX72XX_Clock_RunFrame() {
if (g_animated) {
Run_Animated();
}
}
/*
Config for my clock with IR
startDriver MAX72XX
MAX72XX_Setup 0 1 26
startDriver NTP
@@ -243,9 +224,19 @@ if $CH10==4 then my_send_style_blue
*/
static commandResult_t DRV_MAX72XX_Clock_Animate(const void *context, const char *cmd, const char *args, int flags) {
Tokenizer_TokenizeString(args, 0);
g_animated = Tokenizer_GetArgInteger(0);
return CMD_RES_OK;
}
void DRV_MAX72XX_Clock_Init() {
CMD_RegisterCommand("MAX72XXClock_Animate", DRV_MAX72XX_Clock_Animate, NULL);
}

View File

@@ -32,6 +32,16 @@
#define MAX72XX_DELAY
// #define MAX72XX_DELAY usleep(123);
byte *max_buffer = 0;
int max_buffer_size = 0;
void MAX_FreeBuffer() {
if (max_buffer) {
free(max_buffer);
max_buffer = 0;
}
max_buffer_size = 0;
}
void PORT_shiftOut(int dataPin, int clockPin, int bitOrder, int val, int totalBytes)
{
int i;
@@ -51,6 +61,9 @@ void PORT_shiftOut(int dataPin, int clockPin, int bitOrder, int val, int totalBy
}
void MAX72XX_spiTransfer(max72XX_t *led, int adddr, unsigned char opcode, byte datta) {
if (led == 0) {
return;
}
int offset, maxbytes;
int i;
@@ -70,6 +83,9 @@ void MAX72XX_spiTransfer(max72XX_t *led, int adddr, unsigned char opcode, byte d
HAL_PIN_SetOutputValue(led->port_cs, HIGH);
}
void MAX72XX_shutdown(max72XX_t *led, int addr, bool b) {
if (led == 0) {
return;
}
if (addr < 0 || addr >= led->maxDevices)
return;
if (b)
@@ -78,12 +94,30 @@ void MAX72XX_shutdown(max72XX_t *led, int addr, bool b) {
MAX72XX_spiTransfer(led, addr, OP_SHUTDOWN, 1);
}
void MAX72XX_setScanLimit(max72XX_t *led, int addr, int limit) {
if (led == 0) {
return;
}
if (addr < 0 || addr >= led->maxDevices)
return;
if (limit >= 0 && limit < 8)
MAX72XX_spiTransfer(led, addr, OP_SCANLIMIT, limit);
}
void MAX72XX_clearDisplay(max72XX_t *led, int addr) {
void MAX72XX_clearDisplayFullNoSend(max72XX_t *led) {
if (led == 0) {
return;
}
for (int dev = 0; dev < led->maxDevices; dev++) {
int base = dev * 8;
for (int row = 0; row < 8; row++) {
led->led_status[base + row] = 0;
}
}
}
void MAX72XX_clearDisplayAndSend(max72XX_t *led, int addr) {
if (led == 0) {
return;
}
int offset;
int i;
@@ -97,12 +131,49 @@ void MAX72XX_clearDisplay(max72XX_t *led, int addr) {
}
void MAX72XX_setIntensity(max72XX_t *led, int addr, int intensity) {
if (led == 0) {
return;
}
if (addr < 0 || addr >= led->maxDevices)
return;
if (intensity >= 0 && intensity < 16)
MAX72XX_spiTransfer(led, addr, OP_INTENSITY, intensity);
}
void MAX72XX_free(max72XX_t *led) {
if (led == 0) {
return;
}
free(led->spidata);
free(led->led_status);
free(led);
}
int MAX72XX_countPixels(max72XX_t *led, bool bOn) {
if (led == 0)
return 0;
int count = 0;
int total = led->maxDevices * 8;
if (bOn) {
for (int i = 0; i < total; i++) {
byte v = led->led_status[i];
while (v) {
count += v & 1;
v >>= 1;
}
}
}
else {
count = led->maxDevices * 8 * 8;
}
return count;
}
void MAX72XX_refresh(max72XX_t *led) {
if (led == 0) {
return;
}
int i;
//int mx;
//byte tmp;
@@ -129,6 +200,9 @@ byte Byte_ReverseBits(byte num)
}
void MAX72XX_displayArray(max72XX_t* led, byte *p, int devs, int ofs)
{
if (led == 0) {
return;
}
byte *tg;
int i, mx;
int targetIndex;
@@ -160,25 +234,44 @@ void MAX72XX_displayArray(max72XX_t* led, byte *p, int devs, int ofs)
}
void MAX72XX_shift(max72XX_t *led, int d) {
if (led == 0) {
return;
}
int i;
int mx;
led->scrollCount = (led->scrollCount + d + (led->maxDevices * 8)) % (led->maxDevices * 8);
// byte tmp;
//int offset;
//int row;
byte na[64];
mx = led->maxDevices * 8;
if (mx > max_buffer_size) {
byte *nb;
if (max_buffer) {
nb = (byte*)realloc(max_buffer, mx);
}
else {
nb = (byte*)malloc(mx);
}
if (nb == 0) {
return;
}
max_buffer_size = mx;
max_buffer = nb;
}
for (i = 0; i < mx; i++)
{
na[i] = 0;
max_buffer[i] = 0;
}
if (d == 1)
{
for (i = 0; i < mx; i++)
{
na[i] |= led->led_status[i] << 1;
max_buffer[i] |= led->led_status[i] << 1;
if (led->led_status[i] & 0b10000000 && i > 0)
{
na[(i + 8) % mx] |= 0b00000001;
max_buffer[(i + 8) % mx] |= 0b00000001;
}
}
}
@@ -186,16 +279,16 @@ void MAX72XX_shift(max72XX_t *led, int d) {
{
for (i = 0; i < mx; i++)
{
na[i] |= led->led_status[i] >> 1;
max_buffer[i] |= led->led_status[i] >> 1;
if (led->led_status[i] & 0b00000001 && i > 0)
{
na[(i - 8 + mx) % mx] |= 0b10000000;
max_buffer[(i - 8 + mx) % mx] |= 0b10000000;
}
}
}
for (i = 0; i < mx; i++)
{
led->led_status[i] = na[i];
led->led_status[i] = max_buffer[i];
}
// for(i = 0; i < mx; i++)
// {
@@ -208,6 +301,9 @@ void MAX72XX_shift(max72XX_t *led, int d) {
}
void MAX72XX_setLed(max72XX_t *led, int addr, int row, int column, bool state) {
if (led == 0) {
return;
}
int offset;
byte val = 0x00;
@@ -241,6 +337,9 @@ void MAX72XX_rotate90CW(max72XX_t *led) {
}
void MAX72XX_init(max72XX_t *led) {
if (led == 0) {
return;
}
int i;
HAL_PIN_SetOutputValue(led->port_cs, HIGH);
@@ -252,7 +351,7 @@ void MAX72XX_init(max72XX_t *led) {
MAX72XX_setScanLimit(led, i, 7);
//decode is done in source
MAX72XX_spiTransfer(led, i, OP_DECODEMODE, 0);
MAX72XX_clearDisplay(led, i);
MAX72XX_clearDisplayAndSend(led, i);
//we go into shutdown-mode on startup
MAX72XX_shutdown(led, i, 1);
}
@@ -262,12 +361,17 @@ void MAX72XX_init(max72XX_t *led) {
/* Set the brightness to a medium values */
MAX72XX_setIntensity(led, i, 8);
/* and clear the display */
MAX72XX_clearDisplay(led, i);
MAX72XX_clearDisplayAndSend(led, i);
}
}
void MAX72XX_setupPins(max72XX_t *led, int csi, int clki, int mosii, int maxDevices)
{
if (led == 0) {
return;
}
led->maxDevices = maxDevices;
led->spidata = (byte*)malloc(maxDevices * 2);
led->led_status = (byte*)malloc(maxDevices * 8);
led->port_cs = csi;
led->port_clk = clki;
led->port_mosi = mosii;

View File

@@ -5,14 +5,18 @@
typedef struct max72XX_s {
byte port_clk, port_cs, port_mosi;
byte maxDevices;
unsigned char spidata[16];
byte led_status[8*8];
unsigned char *spidata;
byte *led_status;
int scrollCount;
} max72XX_t;
int MAX72XX_countPixels(max72XX_t *led, bool bOn);
void MAX72XX_refresh(max72XX_t *led);
void MAX72XX_free(max72XX_t *led);
void MAX72XX_shutdown(max72XX_t *led, int addr, bool b);
void MAX72XX_setScanLimit(max72XX_t *led, int addr, int limit);
void MAX72XX_clearDisplay(max72XX_t *led,int addr) ;
void MAX72XX_clearDisplayAndSend(max72XX_t *led,int addr) ;
void MAX72XX_clearDisplayFullNoSend(max72XX_t *led);
void MAX72XX_rotate90CW(max72XX_t *led);
void MAX72XX_setIntensity(max72XX_t *led,int addr, int intensity) ;
void MAX72XX_displayArray(max72XX_t* led, byte *p, int devs, int ofs) ;
@@ -20,4 +24,5 @@ void MAX72XX_shift(max72XX_t *led,int d);
void MAX72XX_setLed(max72XX_t *led,int addr, int row, int column, bool state) ;
void MAX72XX_init(max72XX_t *led);
void MAX72XX_setupPins(max72XX_t *led, int csi, int clki, int mosii, int maxD);
max72XX_t *MAX72XX_alloc();
max72XX_t *MAX72XX_alloc();
void MAX_FreeBuffer();

View File

@@ -358,14 +358,11 @@ static commandResult_t DRV_MAX72XX_Setup(const void *context, const char *cmd, c
int devices;
Tokenizer_TokenizeString(args, 0);
clk = Tokenizer_GetArgInteger(0);
cs = Tokenizer_GetArgInteger(1);
din = Tokenizer_GetArgInteger(2);
devices = Tokenizer_GetArgInteger(3);
//clk = 9;
//cs = 14;
//din = 8;
if (devices == 0) {
devices = 4;
@@ -383,9 +380,36 @@ static commandResult_t DRV_MAX72XX_Setup(const void *context, const char *cmd, c
static commandResult_t DRV_MAX72XX_Scroll(const void *context, const char *cmd, const char *args, int flags) {
if (g_max == 0)
return CMD_RES_ERROR;
MAX72XX_shift(g_max,1);
MAX72XX_refresh(g_max);
int ofs = atoi(args);
if (ofs == 0)
ofs = 1;
MAX72XX_shift(g_max, ofs);
if (0) {
MAX72XX_refresh(g_max);
}
return CMD_RES_OK;
}
int MAX72XXSingle_CountPixels(bool bOn) {
return MAX72XX_countPixels(g_max, bOn);
}
int MAX72XXSingle_GetScrollCount() {
if (g_max == 0)
return 0;
return g_max->scrollCount;
}
static commandResult_t DRV_MAX72XX_Show(const void *context, const char *cmd, const char *args, int flags) {
MAX72XX_refresh(g_max);
return CMD_RES_OK;
}
static commandResult_t DRV_MAX72XX_Clear(const void *context, const char *cmd, const char *args, int flags) {
MAX72XX_clearDisplayFullNoSend(g_max);
if (0) {
MAX72XX_refresh(g_max);
}
return CMD_RES_OK;
}
static commandResult_t DRV_MAX72XX_Print(const void *context, const char *cmd, const char *args, int flags) {
@@ -403,7 +427,9 @@ static commandResult_t DRV_MAX72XX_Print(const void *context, const char *cmd, c
MAX72XX_print(g_max, ofs, args);
MAX72XX_rotate90CW(g_max);
MAX72XX_refresh(g_max);
if (0) {
MAX72XX_refresh(g_max);
}
return CMD_RES_OK;
}
@@ -425,12 +451,17 @@ goto again
*/
void DRV_MAX72XX_Shutdown() {
MAX72XX_free(g_max);
g_max = 0;
MAX_FreeBuffer();
}
// backlog startDriver MAX72XX; MAX72XX_Setup
// MAX72XX_Print 0 1234567
// backlog startDriver MAX72XX; MAX72XX_Setup; MAX72XX_Print 0 1234567
void DRV_MAX72XX_Init() {
//cmddetail:{"name":"MAX72XX_Setup","args":"[Value]",
//cmddetail:{"name":"MAX72XX_Setup","args":"[clk][cs][din][segments]",
//cmddetail:"descr":"Sets the maximum current for LED driver.",
//cmddetail:"fn":"DRV_MAX72XX_Setup","file":"driver/drv_max72xx_single.c","requires":"",
//cmddetail:"examples":""}
@@ -445,6 +476,14 @@ void DRV_MAX72XX_Init() {
//cmddetail:"fn":"DRV_MAX72XX_Print","file":"driver/drv_max72xx_single.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("MAX72XX_Print", DRV_MAX72XX_Print, NULL);
CMD_RegisterCommand("MAX72XX_refresh", DRV_MAX72XX_Show, NULL);
//cmddetail:{"name":"DRV_MAX72XX_Clear","args":"DRV_MAX72XX_Clear",
//cmddetail:"descr":"",
//cmddetail:"fn":"DRV_DRV_MAX72XX_Clear","file":"driver/drv_max72xx_single.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("MAX72XX_Clear", DRV_MAX72XX_Clear, NULL);
}

View File

@@ -0,0 +1,78 @@
#include "../obk_config.h"
#include "drv_local.h"
#include "../logging/logging.h"
#include "../new_cfg.h"
#include "../new_pins.h"
#include "../cmnds/cmd_public.h"
int g_adr = 1;
int g_scl = 0;
int g_sda = 1;
softI2C_t g_scanI2C;
bool canUsePin(int pin) {
#if PLATFORM_ESP8266
if (pin == 6) {
return false;
}
if (pin == 7) {
return false;
}
#endif
return true;
}
static int nextValidPin(int pin) {
do {
pin++;
if (pin >= PLATFORM_GPIO_MAX)
pin = 0;
} while (!canUsePin(pin));
return pin;
}
// startDriver MultiPinI2CScanner
void MultiPinI2CScanner_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState)
{
hprintf255(request, "Scan pins: %i %i, adr %i", g_scl, g_sda, g_adr);
}
void MultiPinI2CScanner_RunFrame() {
g_scanI2C.pin_clk = g_scl;
g_scanI2C.pin_data = g_sda;
Soft_I2C_PreInit(&g_scanI2C);
bool bOk = Soft_I2C_Start(&g_scanI2C, (g_adr << 1) + 0);
Soft_I2C_Stop(&g_scanI2C);
if (bOk) {
addLogAdv(LOG_INFO, LOG_FEATURE_I2C, "Pins SDA = %i, SCL =%i, adr 0x%x (dec %i)\n",
g_sda, g_scl, g_adr);
}
g_adr++;
if (g_adr >= 128) {
g_adr = 0;
// advance SCL
g_scl = nextValidPin(g_scl);
// avoid SDA == SCL
if (g_scl == g_sda)
g_scl = nextValidPin(g_scl);
// if SCL wrapped back to start, move SDA
if (g_scl == 0) {
g_sda = nextValidPin(g_sda);
// avoid SDA == SCL after moving SDA
if (g_scl == g_sda)
g_sda = nextValidPin(g_sda);
}
addLogAdv(LOG_INFO, LOG_FEATURE_I2C, "Next SDA = %i, SCL =%i", g_sda, g_scl);
}
}
void MultiPinI2CScanner_Init() {
}

View File

@@ -31,29 +31,37 @@ xTaskHandle g_weather_thread = NULL;
static char g_request[512];
static char g_reply[1024];
typedef struct weatherData_s {
double lon;
double lat;
char main_weather[32];
char description[32];
double temp;
int pressure;
int humidity;
int timezone;
int sunrise;
int sunset;
} weatherData_t;
typedef struct weatherChannels_s {
byte bInitialized;
char temperature;
char humidity;
char pressure;
} weatherChannels_t;
#include "drv_openWeatherMap.h"
weatherData_t g_weather;
weatherChannels_t g_channels;
weatherData_t *Weather_GetData() {
return &g_weather;
}
static double json_get_double(cJSON *parent, const char *name, double def) {
cJSON *n = cJSON_GetObjectItem(parent, name);
if (n && cJSON_IsNumber(n)) {
return n->valuedouble;
}
return def;
}
static int json_get_int(cJSON *parent, const char *name, int def) {
cJSON *n = cJSON_GetObjectItem(parent, name);
if (n && cJSON_IsNumber(n)) {
return n->valueint;
}
return def;
}
static void json_get_string(cJSON *parent, const char *name, char *dst, int dstSize, const char *def) {
cJSON *n = cJSON_GetObjectItem(parent, name);
const char *src = (n && cJSON_IsString(n)) ? n->valuestring : def;
strncpy(dst, src, dstSize - 1);
dst[dstSize - 1] = '\0';
}
void Weather_SetReply(const char *s) {
const char *json_start = strstr(s, "\r\n\r\n");
if (json_start) {
@@ -62,31 +70,36 @@ void Weather_SetReply(const char *s) {
cJSON *json = cJSON_Parse(json_start);
if (json) {
cJSON *coord = cJSON_GetObjectItem(json, "coord");
if (coord) {
g_weather.lon = cJSON_GetObjectItem(coord, "lon") ? cJSON_GetObjectItem(coord, "lon")->valuedouble : 0.0;
g_weather.lat = cJSON_GetObjectItem(coord, "lat") ? cJSON_GetObjectItem(coord, "lat")->valuedouble : 0.0;
g_weather.lon = json_get_double(coord, "lon", 0.0);
g_weather.lat = json_get_double(coord, "lat", 0.0);
}
cJSON *weather_array = cJSON_GetObjectItem(json, "weather");
if (weather_array && cJSON_IsArray(weather_array)) {
cJSON *weather = cJSON_GetArrayItem(weather_array, 0);
if (weather) {
strncpy(g_weather.main_weather, cJSON_GetObjectItem(weather, "main") ? cJSON_GetObjectItem(weather, "main")->valuestring : "Unknown", sizeof(g_weather.main_weather) - 1);
strncpy(g_weather.description, cJSON_GetObjectItem(weather, "description") ? cJSON_GetObjectItem(weather, "description")->valuestring : "Unknown", sizeof(g_weather.description) - 1);
json_get_string(weather, "main", g_weather.main_weather, sizeof(g_weather.main_weather), "Unknown");
json_get_string(weather, "description", g_weather.description, sizeof(g_weather.description), "Unknown");
}
}
cJSON *main = cJSON_GetObjectItem(json, "main");
if (main) {
g_weather.temp = cJSON_GetObjectItem(main, "temp") ? cJSON_GetObjectItem(main, "temp")->valuedouble : 0.0;
g_weather.pressure = cJSON_GetObjectItem(main, "pressure") ? cJSON_GetObjectItem(main, "pressure")->valueint : 0;
g_weather.humidity = cJSON_GetObjectItem(main, "humidity") ? cJSON_GetObjectItem(main, "humidity")->valueint : 0;
g_weather.temp = json_get_double(main, "temp", 0.0);
g_weather.pressure = json_get_int(main, "pressure", 0);
g_weather.humidity = json_get_int(main, "humidity", 0);
}
g_weather.timezone = cJSON_GetObjectItem(json, "timezone") ? cJSON_GetObjectItem(json, "timezone")->valueint : 0;
g_weather.sunrise = cJSON_GetObjectItem(json, "sys") ? cJSON_GetObjectItem(cJSON_GetObjectItem(json, "sys"), "sunrise")->valueint : 0;
g_weather.sunset = cJSON_GetObjectItem(json, "sys") ? cJSON_GetObjectItem(cJSON_GetObjectItem(json, "sys"), "sunset")->valueint : 0;
g_weather.timezone = json_get_int(json, "timezone", 0);
cJSON *sys = cJSON_GetObjectItem(json, "sys");
if (sys) {
g_weather.sunrise = json_get_int(sys, "sunrise", 0);
g_weather.sunset = json_get_int(sys, "sunset", 0);
}
cJSON_Delete(json);
}
@@ -98,6 +111,7 @@ void Weather_SetReply(const char *s) {
g_reply[0] = '\0';
ADDLOG_ERROR(LOG_FEATURE_HTTP, "No JSON found in reply");
}
if (g_channels.bInitialized) {
if (g_channels.temperature != -1) {
CHANNEL_SetSmart(g_channels.temperature, g_weather.temp, 0);
@@ -110,6 +124,7 @@ void Weather_SetReply(const char *s) {
}
}
}
#if 0
static void sendQueryThreadInternal() {

View File

@@ -0,0 +1,26 @@
#ifndef __DRV_OPENWEATHERMAP_H__
#define __DRV_OPENWEATHERMAP_H__
typedef struct weatherData_s {
double lon;
double lat;
char main_weather[32];
char description[32];
double temp;
int pressure;
int humidity;
int timezone;
int sunrise;
int sunset;
} weatherData_t;
typedef struct weatherChannels_s {
byte bInitialized;
char temperature;
char humidity;
char pressure;
} weatherChannels_t;
weatherData_t *Weather_GetData();
#endif // __DRV_OPENWEATHERMAP_H__

View File

@@ -313,21 +313,22 @@ espPinMapping_t g_pins[] = {
#elif PLATFORM_ESP8266
espPinMapping_t g_pins[] = {
{ "IO0", GPIO_NUM_0, false },
{ "IO1", GPIO_NUM_1, false },
{ "IO2", GPIO_NUM_2, false },
{ "IO3", GPIO_NUM_3, false },
{ "IO4", GPIO_NUM_4, false },
{ "IO5", GPIO_NUM_5, false },
{ "IO9", GPIO_NUM_9, false },
{ "IO10", GPIO_NUM_10, false },
{ "IO12", GPIO_NUM_12, false },
{ "IO13", GPIO_NUM_13, false },
{ "IO14", GPIO_NUM_14, false },
{ "IO15", GPIO_NUM_15, false },
{ "IO16", GPIO_NUM_15, false },
{ "IO0", GPIO_NUM_0, false }, // 0
{ "IO1", GPIO_NUM_1, false }, // 1
{ "IO2", GPIO_NUM_2, false }, // 2
{ "IO3", GPIO_NUM_3, false }, // 3
{ "IO4", GPIO_NUM_4, false }, // 4
{ "IO5", GPIO_NUM_5, false }, // 5
{ "IO9", GPIO_NUM_9, false }, // 6
{ "IO10", GPIO_NUM_10, false }, // 7
{ "IO12", GPIO_NUM_12, false }, // 8
{ "IO13", GPIO_NUM_13, false }, // 9
{ "IO14", GPIO_NUM_14, false }, // 10
{ "IO15", GPIO_NUM_15, false }, // 11
{ "IO16", GPIO_NUM_15, false }, // 12
};
#else
espPinMapping_t g_pins[] = { };

View File

@@ -439,6 +439,50 @@ const char *CFG_GetMQTTPass() {
return g_cfg.mqtt_pass;
}
bool CHANNEL_IsHumidity(int type) {
if (type == ChType_Humidity)
return true;
if (type == ChType_Humidity_div10)
return true;
return false;
}
bool CHANNEL_IsTemperature(int type) {
if (type == ChType_Temperature)
return true;
if (type == ChType_Temperature_div10)
return true;
if (type == ChType_Temperature_div100)
return true;
if (type == ChType_Temperature_div2)
return true;
return false;
}
bool CHANNEL_IsPressure(int type) {
if (type == ChType_Pressure_div100)
return true;
return false;
}
bool CHANNEL_GetGenericOfType(float *out, bool(*checker)(int type)) {
int i, t;
for (i = 0; i < CHANNEL_MAX; i++) {
t = g_cfg.pins.channelTypes[i];
if (checker(t)) {
*out = CHANNEL_GetFinalValue(i);
return true;
}
}
return false;
}
bool CHANNEL_GetGenericHumidity(float *out) {
return CHANNEL_GetGenericOfType(out, CHANNEL_IsHumidity);
}
bool CHANNEL_GetGenericTemperature(float *out) {
return CHANNEL_GetGenericOfType(out, CHANNEL_IsTemperature);
}
bool CHANNEL_GetGenericPressure(float *out) {
return CHANNEL_GetGenericOfType(out, CHANNEL_IsPressure);
}
void CHANNEL_SetType(int ch, int type) {
if (g_cfg.pins.channelTypes[ch] != type) {
g_cfg.pins.channelTypes[ch] = type;

View File

@@ -1584,6 +1584,13 @@ bool CHANNEL_IsPowerRelayChannel(int ch);
// See: enum channelType_t
void CHANNEL_SetType(int ch, int type);
int CHANNEL_GetType(int ch);
bool CHANNEL_IsHumidity(int type);
bool CHANNEL_IsTemperature(int type);
bool CHANNEL_IsPressure(int type);
bool CHANNEL_GetGenericOfType(float *out, bool(*checker)(int type));
bool CHANNEL_GetGenericHumidity(float *out);
bool CHANNEL_GetGenericTemperature(float *out);
bool CHANNEL_GetGenericPressure(float *out);
void CHANNEL_SetFirstChannelByTypeEx(int requiredType, int newVal, int ausemovingaverage);
void CHANNEL_SetFirstChannelByType(int requiredType, int newVal);
// CHANNEL_SET_FLAG_*

View File

@@ -519,6 +519,9 @@
#elif PLATFORM_ESP8266
//#define ENABLE_MULTIPINI2CSCANNER 1
//#define ENABLE_DRIVER_MAX72XX 1
#define ENABLE_SEND_POSTANDGET 1
#define NO_CHIP_TEMPERATURE 1
#define ENABLE_HA_DISCOVERY 1

View File

@@ -360,6 +360,27 @@ void Test_Commands_Channels() {
// cause error
//SELFTEST_ASSERT_CHANNEL(3, 666);
// reset whole device
SIM_ClearOBK(0);
float hum, temp;
SELFTEST_ASSERT(false == CHANNEL_GetGenericHumidity(&hum));
CMD_ExecuteCommand("setChannelType 5 Humidity", 0);
CMD_ExecuteCommand("setChannel 5 88", 0);
SELFTEST_ASSERT(true == CHANNEL_GetGenericHumidity(&hum));
SELFTEST_ASSERT_FLOATCOMPARE(hum, 88.0f);
SELFTEST_ASSERT(false == CHANNEL_GetGenericTemperature(&temp));
CMD_ExecuteCommand("setChannelType 5 Temperature_div10", 0);
SELFTEST_ASSERT(false == CHANNEL_GetGenericHumidity(&hum));
SELFTEST_ASSERT(true == CHANNEL_GetGenericTemperature(&temp));
SELFTEST_ASSERT_FLOATCOMPARE(temp, 8.80f);
CMD_ExecuteCommand("setChannelType 5 Temperature", 0);
SELFTEST_ASSERT(true == CHANNEL_GetGenericTemperature(&temp));
SELFTEST_ASSERT_FLOATCOMPARE(temp, 88.0f);
}

View File

@@ -151,6 +151,8 @@ void Test_Http();
void Test_Demo_ConditionalRelay();
void Test_PIR();
void Test_Driver_TCL_AC();
void Test_MAX72XX();
void Test_OpenWeatherMap();
void Test_GetJSONValue_Setup(const char *text);
void Test_FakeHTTPClientPacket_GET(const char *tg);

View File

@@ -0,0 +1,107 @@
#ifdef WINDOWS
#include "selftest_local.h"
void Test_MAX72XX() {
// reset whole device
SIM_ClearOBK(0);
CMD_ExecuteCommand("startDriver MAX72XX", 0);
CMD_ExecuteCommand("MAX72XX_Setup 10 8 9 16", 0);
CMD_ExecuteCommand("MAX72XX_Print 1232132131212", 0);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
CMD_ExecuteCommand("startDriver MAX72XX", 0);
CMD_ExecuteCommand("MAX72XX_Setup 10 8 9 16", 0);
CMD_ExecuteCommand("MAX72XX_Clear", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 0);
CMD_ExecuteCommand("MAX72XX_Print 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 10);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 1);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 10);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 2);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 10);
CMD_ExecuteCommand("MAX72XX_Print 11", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2*10);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 3);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2*10);
CMD_ExecuteCommand("MAX72XX_Scroll -1", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2*10);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 2);
CMD_ExecuteCommand("MAX72XX_Scroll -3", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2 * 10);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 127);
CMD_ExecuteCommand("MAX72XX_Scroll -10", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2 * 10);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 117);
CMD_ExecuteCommand("MAX72XX_Scroll -20", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2 * 10);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 97);
CMD_ExecuteCommand("MAX72XX_Scroll 20", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2 * 10);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 117);
CMD_ExecuteCommand("MAX72XX_Scroll 10", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 127);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_GetScrollCount() == 0);
for (int i = 0; i < 128; i++) {
CMD_ExecuteCommand("MAX72XX_Scroll -1", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2 * 10);
}
for (int i = 0; i < 128; i++) {
CMD_ExecuteCommand("MAX72XX_Scroll 2", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 2 * 10);
}
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
CMD_ExecuteCommand("startDriver MAX72XX", 0);
CMD_ExecuteCommand("MAX72XX_Setup 10 8 9 64", 0);
CMD_ExecuteCommand("MAX72XX_Print 1232132131212", 0);
CMD_ExecuteCommand("MAX72XX_Scroll 1", 0);
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
CMD_ExecuteCommand("startDriver MAX72XX", 0);
CMD_ExecuteCommand("startDriver MAX72XX_Clock", 0);
Sim_RunSeconds(1, false);
CMD_ExecuteCommand("MAX72XXClock_Animate 1", 0);
Sim_RunSeconds(1, false);
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
CMD_ExecuteCommand("startDriver MAX72XX", 0);
CMD_ExecuteCommand("MAX72XX_Setup 10 8 9 64", 0);
CMD_ExecuteCommand("MAX72XX_Clear", 0);
CMD_ExecuteCommand("MAX72XX_Print 1", 0);
SELFTEST_ASSERT(MAX72XXSingle_CountPixels(true) == 1 * 10);
for (int i = 1; i < 64; i+=23) {
char buff[512];
char buff2[512];
int j;
for ( j = 0; j < i; j++) {
buff[j] = '1';
}
buff[j] = 0;
CMD_ExecuteCommand("MAX72XX_Clear", 0);
strcpy(buff2, "MAX72XX_Print ");
strcat(buff2, buff);
CMD_ExecuteCommand(buff2, 0);
for ( j = 0; j < 3; j++) {
CMD_ExecuteCommand("MAX72XX_Scroll 8", 0);
int act = MAX72XXSingle_CountPixels(true);
SELFTEST_ASSERT(act == i * 10);
}
}
CMD_ExecuteCommand("stopDriver MAX72XX", 0);
}
#endif

View File

@@ -0,0 +1,59 @@
#ifdef WINDOWS
#include "selftest_local.h"
#include "../driver/drv_openWeatherMap.h"
const char *sample_reply =
"HTTP/1.1 200 OK\r\n"
"Date: Sat, 09 Nov 2025 12:00:00 GMT\r\n"
"Server: openweathermap.org\r\n"
"Content-Type: application/json; charset=utf-8\r\n"
"Content-Length: 123\r\n"
"Connection: close\r\n"
"\r\n"
"{"
" \"coord\": {\"lon\": 10.0, \"lat\": 50.0},"
" \"weather\": [{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],"
" \"base\": \"stations\","
" \"main\": {"
" \"temp\": 23.0,"
" \"pressure\": 998,"
" \"humidity\": 85,"
" \"temp_min\": 20.0,"
" \"temp_max\": 25.0"
" },"
" \"visibility\": 10000,"
" \"wind\": {\"speed\": 3.6,\"deg\": 180},"
" \"clouds\": {\"all\": 0},"
" \"dt\": 1604995200,"
" \"sys\": {\"type\":1,\"id\":1234,\"country\":\"US\",\"sunrise\":1604965200,\"sunset\":1605001200},"
" \"timezone\": -18000,"
" \"id\": 123456,"
" \"name\": \"Test City\","
" \"cod\": 200"
"}";
const char *reply_no_weather =
"HTTP/1.1 200 OK\r\n\r\n"
"{\"coord\":{\"lon\":10,\"lat\":50},\"main\":{\"temp\":20,\"pressure\":900,\"humidity\":60}}";
void Test_OpenWeatherMap() {
// HTTP header + json
Weather_SetReply(sample_reply);
weatherData_t *w = Weather_GetData();
SELFTEST_ASSERT_FLOATCOMPARE(w->humidity, 85);
SELFTEST_ASSERT_FLOATCOMPARE(w->pressure, 998);
SELFTEST_ASSERT_FLOATCOMPARE(w->temp, 23);
SELFTEST_ASSERT_STRING(w->main_weather, "Clear");
SELFTEST_ASSERT_STRING(w->description, "clear sky");
SELFTEST_ASSERT_FLOATCOMPARE(w->lat, 50);
SELFTEST_ASSERT_FLOATCOMPARE(w->lon, 10);
}
#endif

View File

@@ -40,13 +40,12 @@
#include "selftest/selftest_local.h"
#include "new_pins.h"
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment(lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "Winmm.lib")
#pragma comment(lib, "Winmm.lib")
int accum_time = 0;
int win_frameNum = 0;
@@ -60,45 +59,46 @@ extern int g_httpPort;
#include <stdint.h>
#include <time.h>
uint32_t timeGetTime() {
uint32_t timeGetTime()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint32_t)((ts.tv_sec * 1000) + (ts.tv_nsec / 1000000));
}
void vTaskDelay(int x) {
void vTaskDelay(int x)
{
}
#endif
void strcat_safe_test(){
void strcat_safe_test()
{
char tmpA[16];
char tmpB[16];
char buff[128];
int res0, res1, res2, res3, res4, res5;
tmpA[0] = 0;
res0 = strcat_safe(tmpA,"Test1",sizeof(tmpA));
res1 = strcat_safe(tmpA," ",sizeof(tmpA));
res2 = strcat_safe(tmpA,"is now processing",sizeof(tmpA));
res3 = strcat_safe(tmpA," very long string",sizeof(tmpA));
res4 = strcat_safe(tmpA," and it",sizeof(tmpA));
res5 = strcat_safe(tmpA," and it",sizeof(tmpA));
res0 = strcat_safe(tmpA, "Test1", sizeof(tmpA));
res1 = strcat_safe(tmpA, " ", sizeof(tmpA));
res2 = strcat_safe(tmpA, "is now processing", sizeof(tmpA));
res3 = strcat_safe(tmpA, " very long string", sizeof(tmpA));
res4 = strcat_safe(tmpA, " and it", sizeof(tmpA));
res5 = strcat_safe(tmpA, " and it", sizeof(tmpA));
tmpB[0] = 0;
res0 = strcat_safe(tmpB,"Test1",sizeof(tmpB));
res1 = strcat_safe(tmpB," ",sizeof(tmpB));
res2 = strcat_safe(tmpB,"is now processing",sizeof(tmpB));
res3 = strcat_safe(tmpB," very long string",sizeof(tmpB));
res4 = strcat_safe(tmpB," and it",sizeof(tmpB));
res5 = strcat_safe(tmpB," and it",sizeof(tmpB));
urldecode2_safe(buff,"qqqqqq%40qqqq",sizeof(buff));
urldecode2_safe(buff,"qqqqqq%40qqqq",sizeof(buff));
res0 = strcat_safe(tmpB, "Test1", sizeof(tmpB));
res1 = strcat_safe(tmpB, " ", sizeof(tmpB));
res2 = strcat_safe(tmpB, "is now processing", sizeof(tmpB));
res3 = strcat_safe(tmpB, " very long string", sizeof(tmpB));
res4 = strcat_safe(tmpB, " and it", sizeof(tmpB));
res5 = strcat_safe(tmpB, " and it", sizeof(tmpB));
urldecode2_safe(buff, "qqqqqq%40qqqq", sizeof(buff));
urldecode2_safe(buff, "qqqqqq%40qqqq", sizeof(buff));
}
void Sim_RunFrame(int frameTime) {
//printf("Sim_RunFrame: frametime %i\n", frameTime);
void Sim_RunFrame(int frameTime)
{
// printf("Sim_RunFrame: frametime %i\n", frameTime);
win_frameNum++;
// this time counter is simulated, I need this for unit tests to work
g_simulatedTimeNow += frameTime;
@@ -106,29 +106,37 @@ void Sim_RunFrame(int frameTime) {
QuickTick(0);
WIN_RunMQTTFrame();
HTTPServer_RunQuickTick();
if (accum_time > 1000) {
if (accum_time > 1000)
{
accum_time -= 1000;
Main_OnEverySecond();
}
}
void Sim_RunMiliseconds(int ms, bool bApplyRealtimeWait) {
while (ms > 0) {
if (bApplyRealtimeWait) {
void Sim_RunMiliseconds(int ms, bool bApplyRealtimeWait)
{
while (ms > 0)
{
if (bApplyRealtimeWait)
{
Sleep(DEFAULT_FRAME_TIME);
}
Sim_RunFrame(DEFAULT_FRAME_TIME);
ms -= DEFAULT_FRAME_TIME;
}
}
void Sim_RunSeconds(float f, bool bApplyRealtimeWait) {
void Sim_RunSeconds(float f, bool bApplyRealtimeWait)
{
int ms = (int)(f * 1000);
Sim_RunMiliseconds(ms, bApplyRealtimeWait);
}
void Sim_RunFrames(int n, bool bApplyRealtimeWait) {
void Sim_RunFrames(int n, bool bApplyRealtimeWait)
{
int i;
for (i = 0; i < n; i++) {
if (bApplyRealtimeWait) {
for (i = 0; i < n; i++)
{
if (bApplyRealtimeWait)
{
Sleep(DEFAULT_FRAME_TIME);
}
Sim_RunFrame(DEFAULT_FRAME_TIME);
@@ -140,8 +148,10 @@ void SIM_Hack_ClearSimulatedPinRoles();
void CHANNEL_FreeLabels();
void SIM_ShutdownOBK() {
if (bObkStarted) {
void SIM_ShutdownOBK()
{
if (bObkStarted)
{
DRV_ShutdownAllDrivers();
#if ENABLE_LITTLEFS
release_lfs();
@@ -162,34 +172,41 @@ void SIM_ShutdownOBK() {
LOG_DeInit();
}
}
void SIM_StartOBK(const char *flashPath) {
void SIM_StartOBK(const char *flashPath)
{
if (flashPath) {
if (flashPath)
{
SIM_SetupFlashFileReading(flashPath);
}
bObkStarted = true;
Main_Init();
}
void SIM_ClearOBK(const char *flashPath) {
void SIM_ClearOBK(const char *flashPath)
{
SIM_ShutdownOBK();
SIM_StartOBK(flashPath);
}
void Test_PartitionSearch() {
void Test_PartitionSearch()
{
SIM_ClearOBK(0);
//SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231N/BK7231N_Milfra_3g_TB11_QIO_2024-20-8-15-32-47.bin");
// SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231N/BK7231N_Milfra_3g_TB11_QIO_2024-20-8-15-32-47.bin");
SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231N/BK7231N_QIO_Adelid_Curtains_MPD-Z_2024-23-10-18-21-33.bin");
//SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231M/SparkleIoT_XH-CB2S_Mini_Switch.bin");
//SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231M/VeSync_Aubess_BSD33_BSDOG02_Plug_1.0.01.bin");
// SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231M/SparkleIoT_XH-CB2S_Mini_Switch.bin");
// SIM_SetupFlashFileReading("W:/GIT/FlashDumps/IoT/BK7231M/VeSync_Aubess_BSD33_BSDOG02_Plug_1.0.01.bin");
CMD_ExecuteCommand("startDriver BKPartitions", 0);
Sim_RunFrames(500000, false);
}
void Win_DoUnitTests() {
//SELFTEST_ASSERT_EXPRESSION("sqrt(4)", 2)
void Win_DoUnitTests()
{
// SELFTEST_ASSERT_EXPRESSION("sqrt(4)", 2)
// Test_PartitionSearch();
Test_OpenWeatherMap();
Test_MAX72XX();
//Test_PartitionSearch();
Test_LEDstrips();
Test_Commands_Channels();
@@ -203,7 +220,6 @@ void Win_DoUnitTests() {
Test_TuyaMCU_Boolean();
Test_TuyaMCU_DP22();
Test_Demo_ConditionalRelay();
Test_Expressions_RunTests_Braces();
Test_Expressions_RunTests_Basic();
@@ -253,7 +269,7 @@ void Win_DoUnitTests() {
Test_MultiplePinsOnChannel();
Test_Flags();
#ifndef LINUX
// TODO: fix on Linux
// TODO: fix on Linux
Test_DHT();
#endif
Test_Tasmota();
@@ -279,31 +295,31 @@ void Win_DoUnitTests() {
Test_Http_LED();
Test_DeviceGroups();
// Just to be sure
// Must be last step
// reset whole device
SIM_ClearOBK(0);
}
long g_delta;
float SIM_GetDeltaTimeSeconds() {
float SIM_GetDeltaTimeSeconds()
{
return g_delta * 0.001f;
}
long start_time = 0;
bool bStartTimeSet = false;
long SIM_GetTime() {
long SIM_GetTime()
{
long cur = timeGetTime();
if (bStartTimeSet == false) {
if (bStartTimeSet == false)
{
start_time = cur;
bStartTimeSet = true;
}
return cur - start_time;
}
// this time counter is simulated, I need this for unit tests to work
int rtos_get_time() {
int rtos_get_time()
{
return g_simulatedTimeNow;
}
int g_bDoingUnitTestsNow = 0;
@@ -313,22 +329,26 @@ int g_bDoingUnitTestsNow = 0;
int SelfTest_GetNumErrors();
extern int g_selfTestsMode;
float myFabs(float f) {
float myFabs(float f)
{
if (f < 0)
return -f;
return f;
}
bool Float_Equals(float a, float b) {
bool Float_Equals(float a, float b)
{
float res = myFabs(a - b);
return res < 0.001f;
}
bool Float_EqualsEpsilon(float a, float b, float epsilon) {
bool Float_EqualsEpsilon(float a, float b, float epsilon)
{
float res = myFabs(a - b);
return res < epsilon;
}
#define VA_BUFFER_SIZE 4096
#define VA_COUNT 4
const char *va(const char *fmt, ...) {
const char *va(const char *fmt, ...)
{
va_list argList;
static int whi = 0;
static char buffer[VA_COUNT][VA_BUFFER_SIZE];
@@ -343,19 +363,20 @@ const char *va(const char *fmt, ...) {
return p;
}
#ifdef LINUX
// fixes - temp
#endif
#if !ENABLE_SDL_WINDOW
bool SIM_ReadDHT11(int pin, byte *data) {
bool SIM_ReadDHT11(int pin, byte *data)
{
return false;
}
void Sim_SendFakeBL0942Packet(float v, float c, float p) {
void Sim_SendFakeBL0942Packet(float v, float c, float p)
{
}
void SIM_GeneratePowerStateDesc(char *o, int outLen) {
void SIM_GeneratePowerStateDesc(char *o, int outLen)
{
*o = 0;
}
#endif
@@ -363,52 +384,66 @@ void SIM_GeneratePowerStateDesc(char *o, int outLen) {
int __cdecl main(int argc, char **argv)
{
bool bWantsUnitTests = 1;
#ifndef LINUX
WSADATA wsaData;
#endif
// clear debug data
if (1) {
if (1)
{
FILE *f = fopen("sim_lastPublishes.txt", "wb");
if (f != 0) {
if (f != 0)
{
fprintf(f, "\n\n");
fclose(f);
}
}
printf("Argc: %i\n", argc);
if (argc > 1) {
if (argc > 1)
{
int value;
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
if (wal_strnicmp(argv[i] + 1, "port", 4) == 0) {
for (int i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
if (wal_strnicmp(argv[i] + 1, "port", 4) == 0)
{
i++;
if (i < argc && sscanf(argv[i], "%d", &value) == 1) {
if (i < argc && sscanf(argv[i], "%d", &value) == 1)
{
g_httpPort = value;
}
} else if (wal_strnicmp(argv[i] + 1, "w", 1) == 0) {
}
else if (wal_strnicmp(argv[i] + 1, "w", 1) == 0)
{
i++;
if (i < argc && sscanf(argv[i], "%d", &value) == 1) {
if (i < argc && sscanf(argv[i], "%d", &value) == 1)
{
#if ENABLE_SDL_WINDOW
SIM_SetWindowW(value);
#endif
}
}
else if (wal_strnicmp(argv[i] + 1, "h", 1) == 0) {
else if (wal_strnicmp(argv[i] + 1, "h", 1) == 0)
{
i++;
if (i < argc && sscanf(argv[i], "%d", &value) == 1) {
if (i < argc && sscanf(argv[i], "%d", &value) == 1)
{
#if ENABLE_SDL_WINDOW
SIM_SetWindowH(value);
#endif
}
}
else if (wal_strnicmp(argv[i] + 1, "runUnitTests", 12) == 0) {
else if (wal_strnicmp(argv[i] + 1, "runUnitTests", 12) == 0)
{
i++;
if (i < argc && sscanf(argv[i], "%d", &value) == 1) {
if (i < argc && sscanf(argv[i], "%d", &value) == 1)
{
// 0 = don't run, 1 = run with system pause, 2 - run without system pause
g_selfTestsMode = value;
}
@@ -418,7 +453,7 @@ int __cdecl main(int argc, char **argv)
}
printf("g_selfTestsMode %i\n", g_selfTestsMode);
int iResult;
int iResult;
#if 0
int maxTest = 100;
@@ -430,12 +465,13 @@ int __cdecl main(int argc, char **argv)
}
#endif
#ifndef LINUX
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
#endif
printf("sizeof(short) = %d\n", (int)sizeof(short));
printf("sizeof(int) = %d\n", (int)sizeof(int));
@@ -446,116 +482,142 @@ int __cdecl main(int argc, char **argv)
printf("sizeof(long double) = %d\n", (int)sizeof(long double));
printf("sizeof(led_corr_t) = %d\n", (int)sizeof(led_corr_t));
printf("sizeof(mainConfig_t) = %d\n", (int)sizeof(mainConfig_t));
if (sizeof(FLASH_VARS_STRUCTURE) != MAGIC_FLASHVARS_SIZE) {
if (sizeof(FLASH_VARS_STRUCTURE) != MAGIC_FLASHVARS_SIZE)
{
printf("sizeof(FLASH_VARS_STRUCTURE) != MAGIC_FLASHVARS_SIZE!: %i\n", sizeof(FLASH_VARS_STRUCTURE));
system("pause");
}
if (sizeof(ledRemap_t) != MAGIC_LED_REMAP_SIZE) {
if (sizeof(ledRemap_t) != MAGIC_LED_REMAP_SIZE)
{
printf("sizeof(ledRemap_t) != MAGIC_LED_REMAP_SIZE!: %i\n", sizeof(ledRemap_t));
system("pause");
}
if (sizeof(led_corr_t) != MAGIC_LED_CORR_SIZE) {
if (sizeof(led_corr_t) != MAGIC_LED_CORR_SIZE)
{
printf("sizeof(led_corr_t) != MAGIC_LED_CORR_SIZE!: %i\n", sizeof(led_corr_t));
system("pause");
}
//printf("Offset MQTT Group: %i", OFFSETOF(mainConfig_t, mqtt_group));
if (sizeof(mainConfig_t) != MAGIC_CONFIG_SIZE_V4) {
// printf("Offset MQTT Group: %i", OFFSETOF(mainConfig_t, mqtt_group));
if (sizeof(mainConfig_t) != MAGIC_CONFIG_SIZE_V4)
{
printf("sizeof(mainConfig_t) != MAGIC_CONFIG_SIZE!: %i\n", sizeof(mainConfig_t));
system("pause");
}
if (OFFSETOF(mainConfig_t, staticIP) != 0x00000527) {
if (OFFSETOF(mainConfig_t, staticIP) != 0x00000527)
{
printf("OFFSETOF(mainConfig_t, staticIP) != 0x00000527z: %i\n", OFFSETOF(mainConfig_t, staticIP));
system("pause");
}
if (OFFSETOF(mainConfig_t, wifi_ssid) != 0x00000014) {
if (OFFSETOF(mainConfig_t, wifi_ssid) != 0x00000014)
{
printf("OFFSETOF(mainConfig_t, wifi_ssid) != 0x00000014: %i\n", OFFSETOF(mainConfig_t, wifi_ssid));
system("pause");
}
if (OFFSETOF(mainConfig_t, wifi_pass) != 0x00000054) {
if (OFFSETOF(mainConfig_t, wifi_pass) != 0x00000054)
{
printf("OFFSETOF(mainConfig_t, wifi_pass) != 0x00000054: %i\n", OFFSETOF(mainConfig_t, wifi_pass));
system("pause");
}
if (OFFSETOF(mainConfig_t, unused_fill) != 0x0000045E) {
if (OFFSETOF(mainConfig_t, unused_fill) != 0x0000045E)
{
printf("OFFSETOF(mainConfig_t, unused_fill) != 0x0000045E: %i\n", OFFSETOF(mainConfig_t, unused_fill));
system("pause");
}
if (OFFSETOF(mainConfig_t, buttonHoldRepeat) != 0x000004BA) {
if (OFFSETOF(mainConfig_t, buttonHoldRepeat) != 0x000004BA)
{
printf("OFFSETOF(mainConfig_t, buttonHoldRepeat) != 0x000004BA: %i\n", OFFSETOF(mainConfig_t, buttonHoldRepeat));
system("pause");
}
if (OFFSETOF(mainConfig_t, shortDeviceName) != 0x2DE) {
if (OFFSETOF(mainConfig_t, shortDeviceName) != 0x2DE)
{
printf("OFFSETOF(mainConfig_t, shortDeviceName) != 0x2DE: %i\n", OFFSETOF(mainConfig_t, shortDeviceName));
system("pause");
}
if (OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull) != 0x00000597) {
if (OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull) != 0x00000597)
{
printf("OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull) != 0x00000597: %i\n", OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull));
system("pause");
}
if (OFFSETOF(mainConfig_t, dgr_sendFlags) != 0x00000460) {
if (OFFSETOF(mainConfig_t, dgr_sendFlags) != 0x00000460)
{
printf("OFFSETOF(mainConfig_t, dgr_sendFlags) != 0x00000460: %i\n", OFFSETOF(mainConfig_t, dgr_sendFlags));
system("pause");
}
if (OFFSETOF(mainConfig_t, mqtt_host) != 0x00000094) {
if (OFFSETOF(mainConfig_t, mqtt_host) != 0x00000094)
{
printf("OFFSETOF(mainConfig_t, mqtt_host) != 0x00000094: %i\n", OFFSETOF(mainConfig_t, mqtt_host));
system("pause");
}
if (OFFSETOF(mainConfig_t, mqtt_userName) != 0x1D4) {
if (OFFSETOF(mainConfig_t, mqtt_userName) != 0x1D4)
{
printf("OFFSETOF(mainConfig_t, mqtt_userName) != 0x1D4: %i\n", OFFSETOF(mainConfig_t, mqtt_userName));
system("pause");
}
if (OFFSETOF(mainConfig_t, mqtt_port) != 0x294) {
}
if (OFFSETOF(mainConfig_t, mqtt_port) != 0x294)
{
printf("OFFSETOF(mainConfig_t, mqtt_port) != 0x294: %i\n", OFFSETOF(mainConfig_t, mqtt_port));
system("pause");
}
if (OFFSETOF(mainConfig_t, mqtt_group) != 0x00000554) {
if (OFFSETOF(mainConfig_t, mqtt_group) != 0x00000554)
{
printf("OFFSETOF(mainConfig_t, mqtt_group) != 0x00000554: %i\n", OFFSETOF(mainConfig_t, mqtt_group));
system("pause");
}
if (OFFSETOF(mainConfig_t, LFS_Size) != 0x000004BC) {
if (OFFSETOF(mainConfig_t, LFS_Size) != 0x000004BC)
{
printf("OFFSETOF(mainConfig_t, LFS_Size) != 0x000004BC: %i\n", OFFSETOF(mainConfig_t, LFS_Size));
system("pause");
}
if (OFFSETOF(mainConfig_t, ping_host) != 0x000005A0) {
if (OFFSETOF(mainConfig_t, ping_host) != 0x000005A0)
{
printf("OFFSETOF(mainConfig_t, ping_host) != 0x000005A0: %i\n", OFFSETOF(mainConfig_t, ping_host));
system("pause");
}
if (OFFSETOF(mainConfig_t, buttonShortPress) != 0x000004B8) {
if (OFFSETOF(mainConfig_t, buttonShortPress) != 0x000004B8)
{
printf("OFFSETOF(mainConfig_t, buttonShortPress) != 0x000004B8: %i\n", OFFSETOF(mainConfig_t, buttonShortPress));
system("pause");
}
if (OFFSETOF(mainConfig_t, pins) != 0x0000033E) {
if (OFFSETOF(mainConfig_t, pins) != 0x0000033E)
{
printf("OFFSETOF(mainConfig_t, pins) != 0x0000033E: %i\n", OFFSETOF(mainConfig_t, pins));
system("pause");
}
if (OFFSETOF(mainConfig_t, version) != 0x00000004) {
if (OFFSETOF(mainConfig_t, version) != 0x00000004)
{
printf("OFFSETOF(mainConfig_t, version) != 0x00000004: %i\n", OFFSETOF(mainConfig_t, version));
system("pause");
}
if (OFFSETOF(mainConfig_t, initCommandLine) != 0x000005E0) {
if (OFFSETOF(mainConfig_t, initCommandLine) != 0x000005E0)
{
printf("OFFSETOF(mainConfig_t, initCommandLine) != 0x000005E0: %i\n", OFFSETOF(mainConfig_t, initCommandLine));
system("pause");
}
if (OFFSETOF(mainConfig_t, wifi_ssid2) != 0x00000C00) {
if (OFFSETOF(mainConfig_t, wifi_ssid2) != 0x00000C00)
{
printf("OFFSETOF(mainConfig_t, wifi_ssid2) != 0x00000C00: %i\n", OFFSETOF(mainConfig_t, wifi_ssid2));
system("pause");
}
if (OFFSETOF(mainConfig_t, wifi_pass2) != 0x00000C40) {
if (OFFSETOF(mainConfig_t, wifi_pass2) != 0x00000C40)
{
printf("OFFSETOF(mainConfig_t, wifi_pass2) != 0x00000C40: %i\n", OFFSETOF(mainConfig_t, wifi_pass2));
system("pause");
}
if (OFFSETOF(mainConfig_t, unused) != 0x00000CA5) {
//printf("OFFSETOF(mainConfig_t, unused) != 0x00000CA5: %i\n", OFFSETOF(mainConfig_t, unused));
//system("pause");
if (OFFSETOF(mainConfig_t, unused) != 0x00000CA5)
{
// printf("OFFSETOF(mainConfig_t, unused) != 0x00000CA5: %i\n", OFFSETOF(mainConfig_t, unused));
// system("pause");
}
// Test expansion
//CMD_UART_Send_Hex(0,0,"FFAA$CH1$BB",0);
// CMD_UART_Send_Hex(0,0,"FFAA$CH1$BB",0);
#ifndef LINUX
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF);
#endif
if (g_selfTestsMode) {
if (g_selfTestsMode)
{
g_bDoingUnitTestsNow = 1;
SIM_ClearOBK(0);
// let things warm up a little
@@ -564,12 +626,12 @@ int __cdecl main(int argc, char **argv)
Win_DoUnitTests();
Sim_RunFrames(50, false);
g_bDoingUnitTestsNow = 0;
if (g_selfTestsMode > 1) {
if (g_selfTestsMode > 1)
{
return SelfTest_GetNumErrors();
}
}
#if ENABLE_SDL_WINDOW
SIM_CreateWindow(argc, argv);
#endif
@@ -586,10 +648,12 @@ int __cdecl main(int argc, char **argv)
CMD_ExecuteCommand("MqttUser homeassistant", 0);
#endif
CMD_ExecuteCommand("reboot", 0);
//CMD_ExecuteCommand("addRepeatingEvent 1 -1 backlog addChannel 1 1; publishInt myTestTopic $CH1", 0);
if (false) {
while (1) {
// CMD_ExecuteCommand("addRepeatingEvent 1 -1 backlog addChannel 1 1; publishInt myTestTopic $CH1", 0);
if (false)
{
while (1)
{
Sleep(DEFAULT_FRAME_TIME);
Sim_RunFrame(DEFAULT_FRAME_TIME);
#if ENABLE_SDL_WINDOW
@@ -597,9 +661,11 @@ int __cdecl main(int argc, char **argv)
#endif
}
}
else {
else
{
long prev_time = SIM_GetTime();
while (1) {
while (1)
{
long cur_time = SIM_GetTime();
g_delta = cur_time - prev_time;
if (g_delta <= 0)
@@ -617,29 +683,26 @@ int __cdecl main(int argc, char **argv)
}
// initialise OTA flash starting at startaddr
int init_ota(unsigned int startaddr) {
int init_ota(unsigned int startaddr)
{
return 0;
}
// add any length of data to OTA
void add_otadata(unsigned char *data, int len) {
void add_otadata(unsigned char *data, int len)
{
return;
}
// finalise OTA flash (write last sector if incomplete)
void close_ota() {
void close_ota()
{
return;
}
void otarequest(const char *urlin) {
void otarequest(const char *urlin)
{
return;
}
#endif