diff --git a/.gitignore b/.gitignore index 10def43f9..a85580d0b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ output/** /custom.mk /.vs .vscode +recents.json node_modules Debug*/** libs_for_simulator/** @@ -21,11 +22,16 @@ ILU.dll ILUT.dll SDL2.dll nfd_d.lib +configMemory.bin /sim_lastPublish_long.txt /sim_lastPublishes.txt /sim_lastPublish.txt +/lastHTTPPacket.txt /lastMQTTPublishSentByOBK.txt *.sln # MacOS ignores .DS_Store + +# MSVC +enc_temp_folder/** diff --git a/docs/README.md b/docs/README.md index 097091412..c7ee06622 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,15 +13,15 @@ Do not add anything here, as it will overwritten with next rebuild. # Doc tables | Section | Comment | |:------------- |------:| -| [IO/Pin Roles](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/ioRoles.md) (77 total) | You can set pin roles in 'Configure Module' section or use one of predefined templates in Web App. For each pin, you also set coresponding channel value. This is needed for modules with multiple relays. If you have 3 relays and 3 buttons, you need to use channel values like 1, 2, and 3. Just enter '1' in the text field, etc. | -| [Flags](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/flags.md) (41 total) | Flags are global and allows you to alter behaviour of the device. | -| [Drivers](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/drivers.md) (36 total) | Drivers allows you to control certain peripherals or enable certain features that are off by default. | -| [Script constants](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/constants.md) (24 total) | Every console command that takes an integer argument supports certain constant expansion. | -| [Channel Types](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/channelTypes.md) (39 total) | Channel types are often not required and don't have to be configured, but in some cases they are required for better device control from OpenBeken web panel. Channel types describes the kind of value stored in channel, for example, if you have a Tuya Fan Controller with 3 speeds control, you can set the channel type to LowMidHigh and it will display the correct UI radiobutton on OpenBeken panel.
Some channels have '_div10' or '_div100' sufixes. This is for TuyaMCU. This is needed because TuyaMCU sends values as integers, so it sends, for example, 215 for 21.5C temperature, and we store it internally as 215 and only convert to float for display. | +| [IO/Pin Roles](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/ioRoles.md) (79 total) | You can set pin roles in 'Configure Module' section or use one of predefined templates in Web App. For each pin, you also set coresponding channel value. This is needed for modules with multiple relays. If you have 3 relays and 3 buttons, you need to use channel values like 1, 2, and 3. Just enter '1' in the text field, etc. | +| [Flags](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/flags.md) (42 total) | Flags are global and allows you to alter behaviour of the device. | +| [Drivers](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/drivers.md) (39 total) | Drivers allows you to control certain peripherals or enable certain features that are off by default. | +| [Script constants](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/constants.md) (27 total) | Every console command that takes an integer argument supports certain constant expansion. | +| [Channel Types](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/channelTypes.md) (40 total) | Channel types are often not required and don't have to be configured, but in some cases they are required for better device control from OpenBeken web panel. Channel types describes the kind of value stored in channel, for example, if you have a Tuya Fan Controller with 3 speeds control, you can set the channel type to LowMidHigh and it will display the correct UI radiobutton on OpenBeken panel.
Some channels have '_div10' or '_div100' sufixes. This is for TuyaMCU. This is needed because TuyaMCU sends values as integers, so it sends, for example, 215 for 21.5C temperature, and we store it internally as 215 and only convert to float for display. | | [FAQ](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/faq.md) (27 total) | Here is a detailed list of questions you may ask. Some information from docs is repeated here. | -| [Console/Script commands](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/commands.md) (262 total) | There are multiple console commands that allow you to automate your devices. Commands can be entered manually in command line, can be send by HTTP (just like in Tasmota), can be send by MQTT and also can be scripted. | +| [Console/Script commands](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/commands.md) (277 total) | There are multiple console commands that allow you to automate your devices. Commands can be entered manually in command line, can be send by HTTP (just like in Tasmota), can be send by MQTT and also can be scripted. | | [Command Examples](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/commandExamples.md) (10 total) | Here you can find some examples of console commands usage | | [Autoexec.bat examples (configs)](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/autoexecExamples.md) (15 total) | Here you can find examples of autoexec.bat configs. The autoexec.bat file can be created in Web Application, under LittleFS tab, and is run every time device reboots (unless device enters safe mode/AP mode). The autoexec.bat file allows you to create more advanced configs, setup TuyaMCU mappings, etc | | [MQTT Topics](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/mqttTopics.md) (25 total) | MQTT topic names and content for incoming and ougoing OBK MQTT publishes | | [Script examples](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/scriptExamples.md) (5 total) | Scripts can be put in autoexec.bat and then they will start automatically on reboot, you can also put script in other LittleFS file and use startScript [fileName] [Label] command to run them. From the firmware point of view, scripts and autoexecs are basically the same thing. There is, however, a little bit more advanced system of execution for scripts which can be written in a form of scripts threads that run over time, can have delays within then, conditional checks and jumps. | -| [Console/Script commands [Extended Edition]](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/commands-extended.md) (262 total) | More details on commands. | +| [Console/Script commands [Extended Edition]](https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/commands-extended.md) (277 total) | More details on commands. | diff --git a/docs/channelTypes.md b/docs/channelTypes.md index 912afd96d..6ce343579 100644 --- a/docs/channelTypes.md +++ b/docs/channelTypes.md @@ -43,4 +43,5 @@ Do not add anything here, as it will overwritten with next rebuild. | Power_div10 | Just like power, but with one decimal place (but stored as integer, for TuyaMCU support) | | ReadOnlyLowMidHigh | Like LowMidHigh, but just read only | | SmokePercent | Smoke percentage | +| Illuminance | Illuminance in Lux | | Max | This is the current total number of available channel types. | diff --git a/docs/commands-extended.md b/docs/commands-extended.md index 79eaebb4b..afca0bb62 100644 --- a/docs/commands-extended.md +++ b/docs/commands-extended.md @@ -62,6 +62,7 @@ Do not add anything here, as it will overwritten with next rebuild. | echo | [Message] | Sends given message back to console. This command expands variables, so writing $CH12 will print value of channel 12, etc. Remember that you can also use special channel indices to access persistant flash variables and to access LED variables like dimmer, etc. | File: cmnds/cmd_main.c
Function: CMD_Echo | | EnergyCntReset | | Resets the total Energy Counter, the one that is usually kept after device reboots. After this commands, the counter will start again from 0. | File: driver/drv_bl_shared.c
Function: BL09XX_ResetEnergyCounter | | exec | [Filename] | exec - run autoexec.bat or other file from LFS if present | File: cmnds/cmd_tasmota.c
Function: cmnd_lfsexec | +| ExitSimulator | | [SIMULATOR ONLY] Exits the application instance | File: cmnds/cmd_simulatorOnly.c
Function: CMD_ExitSimulator | | fakeTuyaPacket | [HexString] | This simulates packet being sent from TuyaMCU to our OBK device. | File: driver/drv_tuyaMCU.c
Function: TuyaMCU_FakePacket | | flags | [IntegerValue] | Sets the device flags | File: cmnds/cmd_main.c
Function: CMD_Flags | | FriendlyName | [Name] | Sets the full name of the device | File: cmnds/cmd_channels.c
Function: CMD_FriendlyName | @@ -73,10 +74,18 @@ Do not add anything here, as it will overwritten with next rebuild. | HSBColor1 | [Hue] | Tasmota-style colour access. Sets hue in 0 to 360 range. | File: cmnds/cmd_newLEDDriver.c
Function: setHue | | HSBColor2 | [Saturation] | Tasmota-style colour access. Set saturation in 0 to 100 range. | File: cmnds/cmd_newLEDDriver.c
Function: setSaturation | | HSBColor3 | [Brightness] | Tasmota-style colour access. Sets brightness in 0 to 100 range. | File: cmnds/cmd_newLEDDriver.c
Function: setBrightness | +| HT16K33_Blink | HT16K33_Blink | | File: driver/drv_ht16k33.c
Function: NULL); | +| HT16K33_Brightness | HT16K33_Brightness | | File: driver/drv_ht16k33.c
Function: NULL); | +| HT16K33_Char | HT16K33_Char | | File: driver/drv_ht16k33.c
Function: NULL); | +| HT16K33_Print | HT16K33_Print | | File: driver/drv_ht16k33.c
Function: NULL); | +| HT16K33_Raw | HT16K33_Raw | | File: driver/drv_ht16k33.c
Function: NULL); | +| HT16K33_Test | HT16K33_Test | | File: driver/drv_ht16k33.c
Function: NULL); | | if | [Condition]['then'][CommandA]['else'][CommandB] | Executed a conditional. Condition should be single line. You must always use 'then' after condition. 'else' is optional. Use aliases or quotes for commands with spaces | File: cmnds/cmd_main.c
Function: CMD_If | | IREnable | [Str][1or0] | Enable/disable aspects of IR. IREnable RXTX 0/1 - enable Rx whilst Tx. IREnable [protocolname] 0/1 - enable/disable a specified protocol | File: driver/drv_ir.cpp
Function: IR_Enable | | IRSend | [PROT-ADDR-CMD-REP] | Sends IR commands in the form PROT-ADDR-CMD-REP, e.g. NEC-1-1A-0 | File: driver/drv_ir.cpp
Function: IR_Send_Cmd | | json_test | cmnd_json_test | | File: cmnds/cmd_test.c
Function: NULL); | +| KP18058_Map | [Ch0][Ch1][Ch2][Ch3][Ch4] | Maps KP18058_Map RGBCW values to given indices of KP18058 channels. This is because KP18058 channels order is not the same for some devices. Some devices are using RGBCW order and some are using GBRCW, etc, etc. Example usage: KP18058_Map 0 1 2 3 4 | File: driver/drv_sm2235.c
Function: KP18058_Map | +| KP18058_RGBCW | [HexColor] | Don't use it. It's for direct access of KP18058 driver. You don't need it because LED driver automatically calls it, so just use led_basecolor_rgb | File: driver/drv_bp5758d.c
Function: KP18058_RGBCW | | lcd_clear | | Clears the LCD | File: i2c/drv_i2c_lcd_pcf8574t.c
Function: DRV_I2C_LCD_PCF8574_Clear | | lcd_clearAndGoto | | Clears LCD and go to pos | File: i2c/drv_i2c_lcd_pcf8574t.c
Function: DRV_I2C_LCD_PCF8574_ClearAndGoTo | | lcd_goto | | Go to position on LCD | File: i2c/drv_i2c_lcd_pcf8574t.c
Function: DRV_I2C_LCD_PCF8574_GoTo | @@ -126,6 +135,11 @@ Do not add anything here, as it will overwritten with next rebuild. | MAX72XX_Scroll | DRV_MAX72XX_Scroll | | File: driver/drv_max72xx_single.c
Function: NULL); | | MAX72XX_Setup | [Value] | Sets the maximum current for LED driver. | File: driver/drv_sm2135.c
Function: SM2135_Current | | MCP23017_MapPinToChannel | | Maps port expander bit to OBK channel | File: i2c/drv_i2c_main.c
Function: DRV_I2C_MCP23017_MapPinToChannel | +| MCP9808_Adr | MCP9808_Adr | | File: driver/drv_mcp9808.c
Function: NULL); | +| MCP9808_AlertMin | MCP9808_AlertMin | | File: driver/drv_mcp9808.c
Function: NULL); | +| MCP9808_AlertRange | MCP9808_AlertRange | | File: driver/drv_mcp9808.c
Function: NULL); | +| MCP9808_Calibrate | MCP9808_Calibrate | | File: driver/drv_mcp9808.c
Function: NULL); | +| MCP9808_Cycle | MCP9808_cycle | | File: driver/drv_mcp9808.c
Function: NULL); | | MqttClient | [ValueString] | Sets the MQTT client. Command keeps Tasmota syntax | File: cmnds/cmd_tasmota.c
Function: cmnd_MqttClient | | MqttHost | [ValueString] | Sets the MQTT host. Command keeps Tasmota syntax | File: cmnds/cmd_tasmota.c
Function: cmnd_MqttHost | | MqttPassword | [ValueString] | Sets the MQTT pass. Command keeps Tasmota syntax | File: cmnds/cmd_tasmota.c
Function: cmnd_MqttPassword | @@ -163,7 +177,7 @@ Do not add anything here, as it will overwritten with next rebuild. | scanI2C | | | File: i2c/drv_i2c_main.c
Function: DRV_I2C_MCP23017_MapPinToChannel | | scheduleHADiscovery | [Seconds] | This will schedule HA discovery, the discovery will happen with given number of seconds, but timer only counts when MQTT is connected. It will not work without MQTT online, so you must set MQTT credentials first. | File: cmnds/cmd_main.c
Function: CMD_ScheduleHADiscovery | | sendGet | [TargetURL] | Sends a HTTP GET request to target URL. May include GET arguments. Can be used to control devices by Tasmota HTTP protocol. Command supports argument expansion, so $CH11 changes to value of channel 11, etc, etc. | File: cmnds/cmd_send.c
Function: CMD_SendGET | -| sendPOST | CMD_SendPOST | | File: cmnds/cmd_send.c
Function: NULL); | +| sendPOST | [TargetURL] [HTTP Port] [Content Type] [Post Content] | Sends a HTTP POST request to target URL. Arguments can contain variable expansion. | File: cmnds/cmd_send.c
Function: CMD_SendPOST | | setButtonColor | [ButtonIndex][Color] | Sets the colour of custom scriptable HTTP page button | File: driver/drv_httpButtons.c
Function: CMD_setButtonColor | | setButtonCommand | [ButtonIndex][Command] | Sets the command of custom scriptable HTTP page button | File: driver/drv_httpButtons.c
Function: CMD_setButtonCommand | | setButtonEnabled | [ButtonIndex][1or0] | Sets the visibility of custom scriptable HTTP page button | File: driver/drv_httpButtons.c
Function: CMD_setButtonEnabled | @@ -200,10 +214,9 @@ Do not add anything here, as it will overwritten with next rebuild. | SHT_SetAlert | [temp_high, temp_low, hum_high, hum_low]
Req:all | Set Sensor alert configuration
e.g.:SHT_SetAlertCmd | File: driver/drv_sht3x.c
Function: SHT3X_SetAlertcmd | | SHT_StopPer | | Stop periodical capture for SHT Sensor | File: driver/drv_sht3x.c
Function: SHT3X_StopPerCmd | | simonirtest | | Simons Special Test | File: cmnds/cmd_main.c
Function: CMD_SimonTest | -| SM16703P_Send | | NULL | File: driver/drv_sm16703P.c
Function: SM16703P_Send_Cmd | -| SM16703P_Test | | qq | File: driver/drv_ucs1912.c
Function: SM16703P_Test | -| SM16703P_Test_3xOne | | NULL | File: driver/drv_sm16703P.c
Function: SM16703P_Test_3xOne | -| SM16703P_Test_3xZero | | NULL | File: driver/drv_sm16703P.c
Function: SM16703P_Test_3xZero | +| SM16703P_Init | SM16703P_Start | | File: driver/drv_sm16703P.c
Function: NULL); | +| SM16703P_SetPixel | SM16703P_CMD_setPixel | | File: driver/drv_sm16703P.c
Function: NULL); | +| SM16703P_Start | SM16703P_StartTX | | File: driver/drv_sm16703P.c
Function: NULL); | | SM2135_Current | [RGBLimit][CWLimit] | Sets the maximum current for LED driver. Please note that arguments are using SM2135 codes, see [full list of codes here](https://www.elektroda.com/rtvforum/viewtopic.php?p=20493415#20493415) | File: driver/drv_sm2135.c
Function: SM2135_Current | | SM2135_Map | [Ch0][Ch1][Ch2][Ch3][Ch4] | Maps the RGBCW values to given indices of SM2135 channels. This is because SM2135 channels order is not the same for some devices. Some devices are using RGBCW order and some are using GBRCW, etc, etc. Example usage: SM2135_Map 0 1 2 3 4 | File: driver/drv_sm2135.c
Function: SM2135_Map | | SM2135_RGBCW | [HexColor] | Don't use it. It's for direct access of SM2135 driver. You don't need it because LED driver automatically calls it, so just use led_basecolor_rgb | File: driver/drv_sm2135.c
Function: SM2135_RGBCW | @@ -247,6 +260,7 @@ Do not add anything here, as it will overwritten with next rebuild. | toggler_name | | Handles toggler_name0, toggler_name1, etc. Sets the name of a toggler for GUI. | File: driver/drv_pwmToggler.c
Function: Toggler_NameX | | toggler_set | [Value] | Sets the VALUE of given output. Handles toggler_set0, toggler_set1, etc. The last digit after command name is changed to slot index. | File: driver/drv_pwmToggler.c
Function: Toggler_SetX | | tuyaMcu_defWiFiState | | Command sets the default WiFi state for TuyaMCU when device is not online. It may be required for some devices to work, because Tuya designs them to ignore touch buttons or beep when not paired. Please see [values table and description here](https://www.elektroda.com/rtvforum/viewtopic.php?p=20483899#20483899). | File: driver/drv_tuyaMCU.c
Function: Cmd_TuyaMCU_Send_RSSI | +| tuyaMcu_sendColor | Cmd_TuyaMCU_SendColor | | File: driver/drv_tuyaMCU.c
Function: NULL); | | tuyaMcu_sendCurTime | | Sends a current date by TuyaMCU to clock/callendar MCU. Time is taken from NTP driver, so NTP also should be already running. | File: driver/drv_tuyaMCU.c
Function: TuyaMCU_Send_SetTime_Current | | tuyaMcu_sendHeartbeat | | Send heartbeat to TuyaMCU | File: driver/drv_tuyaMCU.c
Function: TuyaMCU_SendHeartbeat | | tuyaMcu_sendMCUConf | | Send MCU conf command | File: driver/drv_tuyaMCU.c
Function: TuyaMCU_SendMCUConf | @@ -256,6 +270,7 @@ Do not add anything here, as it will overwritten with next rebuild. | tuyaMcu_sendState | [dpID][dpType][dpValue] | Manually send set state command. Do not use it. Use mapping, so communication is bidirectional and automatic. | File: driver/drv_tuyaMCU.c
Function: TuyaMCU_SendStateCmd | | tuyaMcu_setBaudRate | [BaudValue] | Sets the baud rate used by TuyaMCU UART communication. Default value is 9600. Some other devices require 115200. | File: driver/drv_tuyaMCU.c
Function: TuyaMCU_SetBaudRate | | tuyaMcu_setDimmerRange | [Min][Max] | Set dimmer range used by TuyaMCU | File: driver/drv_tuyaMCU.c
Function: TuyaMCU_SetDimmerRange | +| tuyaMcu_setupLED | Cmd_TuyaMCU_SetupLED | | File: driver/drv_tuyaMCU.c
Function: NULL); | | tuyaMcu_testSendTime | | Sends a example date by TuyaMCU to clock/callendar MCU | File: driver/drv_tuyaMCU.c
Function: TuyaMCU_Send_SetTime_Example | | uartFakeHex | [HexString] | Spoofs a fake hex packet so it looks like TuyaMCU send that to us. Used for testing. | File: driver/drv_uart.c
Function: CMD_UART_FakeHex | | uartInit | [BaudRate] | Manually starts UART1 port. Keep in mind that you don't need to do it for TuyaMCU and BL0942, those drivers do it automatically. | File: driver/drv_uart.c
Function: CMD_UART_Init | diff --git a/docs/commands.md b/docs/commands.md index 652cc4214..3f9848c59 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -65,6 +65,7 @@ Do not add anything here, as it will overwritten with next rebuild. | echo | [Message] | Sends given message back to console. This command expands variables, so writing $CH12 will print value of channel 12, etc. Remember that you can also use special channel indices to access persistant flash variables and to access LED variables like dimmer, etc. | | EnergyCntReset | | Resets the total Energy Counter, the one that is usually kept after device reboots. After this commands, the counter will start again from 0. | | exec | [Filename] | exec - run autoexec.bat or other file from LFS if present | +| ExitSimulator | | [SIMULATOR ONLY] Exits the application instance | | fakeTuyaPacket | [HexString] | This simulates packet being sent from TuyaMCU to our OBK device. | | flags | [IntegerValue] | Sets the device flags | | FriendlyName | [Name] | Sets the full name of the device | @@ -76,10 +77,18 @@ Do not add anything here, as it will overwritten with next rebuild. | HSBColor1 | [Hue] | Tasmota-style colour access. Sets hue in 0 to 360 range. | | HSBColor2 | [Saturation] | Tasmota-style colour access. Set saturation in 0 to 100 range. | | HSBColor3 | [Brightness] | Tasmota-style colour access. Sets brightness in 0 to 100 range. | +| HT16K33_Blink | HT16K33_Blink | | +| HT16K33_Brightness | HT16K33_Brightness | | +| HT16K33_Char | HT16K33_Char | | +| HT16K33_Print | HT16K33_Print | | +| HT16K33_Raw | HT16K33_Raw | | +| HT16K33_Test | HT16K33_Test | | | if | [Condition]['then'][CommandA]['else'][CommandB] | Executed a conditional. Condition should be single line. You must always use 'then' after condition. 'else' is optional. Use aliases or quotes for commands with spaces | | IREnable | [Str][1or0] | Enable/disable aspects of IR. IREnable RXTX 0/1 - enable Rx whilst Tx. IREnable [protocolname] 0/1 - enable/disable a specified protocol | | IRSend | [PROT-ADDR-CMD-REP] | Sends IR commands in the form PROT-ADDR-CMD-REP, e.g. NEC-1-1A-0 | | json_test | cmnd_json_test | | +| KP18058_Map | [Ch0][Ch1][Ch2][Ch3][Ch4] | Maps KP18058_Map RGBCW values to given indices of KP18058 channels. This is because KP18058 channels order is not the same for some devices. Some devices are using RGBCW order and some are using GBRCW, etc, etc. Example usage: KP18058_Map 0 1 2 3 4 | +| KP18058_RGBCW | [HexColor] | Don't use it. It's for direct access of KP18058 driver. You don't need it because LED driver automatically calls it, so just use led_basecolor_rgb | | lcd_clear | | Clears the LCD | | lcd_clearAndGoto | | Clears LCD and go to pos | | lcd_goto | | Go to position on LCD | @@ -129,6 +138,11 @@ Do not add anything here, as it will overwritten with next rebuild. | MAX72XX_Scroll | DRV_MAX72XX_Scroll | | | MAX72XX_Setup | [Value] | Sets the maximum current for LED driver. | | MCP23017_MapPinToChannel | | Maps port expander bit to OBK channel | +| MCP9808_Adr | MCP9808_Adr | | +| MCP9808_AlertMin | MCP9808_AlertMin | | +| MCP9808_AlertRange | MCP9808_AlertRange | | +| MCP9808_Calibrate | MCP9808_Calibrate | | +| MCP9808_Cycle | MCP9808_cycle | | | MqttClient | [ValueString] | Sets the MQTT client. Command keeps Tasmota syntax | | MqttHost | [ValueString] | Sets the MQTT host. Command keeps Tasmota syntax | | MqttPassword | [ValueString] | Sets the MQTT pass. Command keeps Tasmota syntax | @@ -166,7 +180,7 @@ Do not add anything here, as it will overwritten with next rebuild. | scanI2C | | | | scheduleHADiscovery | [Seconds] | This will schedule HA discovery, the discovery will happen with given number of seconds, but timer only counts when MQTT is connected. It will not work without MQTT online, so you must set MQTT credentials first. | | sendGet | [TargetURL] | Sends a HTTP GET request to target URL. May include GET arguments. Can be used to control devices by Tasmota HTTP protocol. Command supports argument expansion, so $CH11 changes to value of channel 11, etc, etc. | -| sendPOST | CMD_SendPOST | | +| sendPOST | [TargetURL] [HTTP Port] [Content Type] [Post Content] | Sends a HTTP POST request to target URL. Arguments can contain variable expansion. | | setButtonColor | [ButtonIndex][Color] | Sets the colour of custom scriptable HTTP page button | | setButtonCommand | [ButtonIndex][Command] | Sets the command of custom scriptable HTTP page button | | setButtonEnabled | [ButtonIndex][1or0] | Sets the visibility of custom scriptable HTTP page button | @@ -203,10 +217,9 @@ Do not add anything here, as it will overwritten with next rebuild. | SHT_SetAlert | [temp_high, temp_low, hum_high, hum_low]
Req:all | Set Sensor alert configuration
e.g.:SHT_SetAlertCmd | | SHT_StopPer | | Stop periodical capture for SHT Sensor | | simonirtest | | Simons Special Test | -| SM16703P_Send | | NULL | -| SM16703P_Test | | qq | -| SM16703P_Test_3xOne | | NULL | -| SM16703P_Test_3xZero | | NULL | +| SM16703P_Init | SM16703P_Start | | +| SM16703P_SetPixel | SM16703P_CMD_setPixel | | +| SM16703P_Start | SM16703P_StartTX | | | SM2135_Current | [RGBLimit][CWLimit] | Sets the maximum current for LED driver. Please note that arguments are using SM2135 codes, see [full list of codes here](https://www.elektroda.com/rtvforum/viewtopic.php?p=20493415#20493415) | | SM2135_Map | [Ch0][Ch1][Ch2][Ch3][Ch4] | Maps the RGBCW values to given indices of SM2135 channels. This is because SM2135 channels order is not the same for some devices. Some devices are using RGBCW order and some are using GBRCW, etc, etc. Example usage: SM2135_Map 0 1 2 3 4 | | SM2135_RGBCW | [HexColor] | Don't use it. It's for direct access of SM2135 driver. You don't need it because LED driver automatically calls it, so just use led_basecolor_rgb | @@ -250,6 +263,7 @@ Do not add anything here, as it will overwritten with next rebuild. | toggler_name | | Handles toggler_name0, toggler_name1, etc. Sets the name of a toggler for GUI. | | toggler_set | [Value] | Sets the VALUE of given output. Handles toggler_set0, toggler_set1, etc. The last digit after command name is changed to slot index. | | tuyaMcu_defWiFiState | | Command sets the default WiFi state for TuyaMCU when device is not online. It may be required for some devices to work, because Tuya designs them to ignore touch buttons or beep when not paired. Please see [values table and description here](https://www.elektroda.com/rtvforum/viewtopic.php?p=20483899#20483899). | +| tuyaMcu_sendColor | Cmd_TuyaMCU_SendColor | | | tuyaMcu_sendCurTime | | Sends a current date by TuyaMCU to clock/callendar MCU. Time is taken from NTP driver, so NTP also should be already running. | | tuyaMcu_sendHeartbeat | | Send heartbeat to TuyaMCU | | tuyaMcu_sendMCUConf | | Send MCU conf command | @@ -259,6 +273,7 @@ Do not add anything here, as it will overwritten with next rebuild. | tuyaMcu_sendState | [dpID][dpType][dpValue] | Manually send set state command. Do not use it. Use mapping, so communication is bidirectional and automatic. | | tuyaMcu_setBaudRate | [BaudValue] | Sets the baud rate used by TuyaMCU UART communication. Default value is 9600. Some other devices require 115200. | | tuyaMcu_setDimmerRange | [Min][Max] | Set dimmer range used by TuyaMCU | +| tuyaMcu_setupLED | Cmd_TuyaMCU_SetupLED | | | tuyaMcu_testSendTime | | Sends a example date by TuyaMCU to clock/callendar MCU | | uartFakeHex | [HexString] | Spoofs a fake hex packet so it looks like TuyaMCU send that to us. Used for testing. | | uartInit | [BaudRate] | Manually starts UART1 port. Keep in mind that you don't need to do it for TuyaMCU and BL0942, those drivers do it automatically. | diff --git a/docs/constants.md b/docs/constants.md index b43551a79..4682287fd 100644 --- a/docs/constants.md +++ b/docs/constants.md @@ -11,6 +11,8 @@ Do not add anything here, as it will overwritten with next rebuild. | $CH*** | Provides channel access, so you can do math expressions on channel values. $CH1 is channel 1, $CH20 is channel 20, $CH140 is channel 140, etc | | $CH** | Provides channel access, as above. | | $CH* | Provides channel access, as above. | +| $FLAG** | Provides flag access, as above. | +| $FLAG* | Provides flag access, as above. | | $led_dimmer | Current value of LED dimmer, 0-100 range | | $led_enableAll | Returns 1 if LED is enabled, otherwise 0. | | $led_hue | Current LED Hue value | @@ -23,6 +25,7 @@ Do not add anything here, as it will overwritten with next rebuild. | $voltage | Current value of voltage from energy metering chip. You can use those variables to make, for example, a change handler that fires when voltage is above 245, etc. | | $current | Current value of current from energy metering chip | | $power | Current value of power from energy metering chip | +| $energy | Current value of energy counter from energy metering chip | | $day | Current weekday from NTP | | $hour | Current hour from NTP | | $minute | Current minute from NTP | diff --git a/docs/drivers.md b/docs/drivers.md index 8d2ab102b..48ddad023 100644 --- a/docs/drivers.md +++ b/docs/drivers.md @@ -22,8 +22,9 @@ Do not add anything here, as it will overwritten with next rebuild. | IR | IRLibrary wrapper, so you can receive remote signals and send them. See [forum discussion here](https://www.elektroda.com/rtvforum/topic3920360.html), also see [LED strip and IR YT video](https://www.youtube.com/watch?v=KU0tDwtjfjw) | | DDP | DDP is a LED control protocol that is using UDP. You can use xLights or any other app to control OBK LEDs that way. | | SSDP | SSDP is a discovery protocol, so BK devices can show up in, for example, Windows network section | -| Wemo | Wemo emulation for Alexa. You must also start SSDP so it can run, because it depends on SSDP discovery. | | DGR | Tasmota Device groups driver. See [forum example](https://www.elektroda.com/rtvforum/topic3925472.html) and TODO-video tutorial (will post on YT soon) | +| Wemo | Wemo emulation for Alexa. You must also start SSDP so it can run, because it depends on SSDP discovery. | +| Hue | Hue emulation for Alexa. You must also start SSDP so it can run, because it depends on SSDP discovery. | | PWMToggler | PWMToggler is a custom abstraction layer that can run on top of raw PWM channels. It provides ability to turn off/on the PWM while keeping it's value, which is not possible by direct channel operations. It can be used for some custom devices with extra lights/lasers. See example [here](https://www.elektroda.com/rtvforum/topic3939064.html). | | DoorSensor | DoorSensor is using deep sleep to preserve battery. This is used for devices without TuyaMCU, where BK deep sleep and wakeup on GPIO is used. This drives requires you to set a DoorSensor pin. Change on door sensor pin wakes up the device. If there are no changes for some time, device goes to sleep. See example [here](https://www.elektroda.com/rtvforum/topic3960149.html). If your door sensor does not wake up in certain pos, please use DSEdge command (try all 3 options, default is 2). | | MAX72XX_Clock | Simple hardcoded driver for MAX72XX clock. Requirex manual start of MAX72XX driver with MAX72XX setup and NTP start. | @@ -33,11 +34,13 @@ Do not add anything here, as it will overwritten with next rebuild. | BP1658CJ | BP1658CJ custom-'I2C' LED driver for RGBCW lights. This will start automatically if you set both BP1658CJ pin roles. This may need you to remap the RGBCW indexes with BP1658CJ_Map command | | SM2235 | SM2335 andd SM2235 custom-'I2C' LED driver for RGBCW lights. This will start automatically if you set both SM2235 pin roles. This may need you to remap the RGBCW indexes with SM2235_Map command | | CHT8305 | CHT8305 is a Temperature and Humidity sensor with I2C interface. | -| KP18068 | KP18068 I2C LED driver | -| MAX72XX | MAX72XX LED matrix display driver with font and simple script interface. | +| KP18068 | KP18068 I2C LED driver. Unfinished due to the lack of the information. | +| KP18058 | KP18058 I2C LED driver. Working, see reverse-engineering [topic](https://www.elektroda.pl/rtvforum/topic3991620.html) | +| MAX72XX | MAX72XX LED matrix display driver with font and simple script interface. See [protocol explanation](https://www.elektroda.pl/rtvforum/viewtopic.php?p=18040628#18040628) | | TM1637 | Driver for 7-segment LED display with DIO/CLK interface | | GN6932 | Driver for 7-segment LED display with DIO/CLK/STB interface. See [this topic](https://www.elektroda.com/rtvforum/topic3971252.html) for details. | | TM1638 | Driver for 7-segment LED display with DIO/CLK/STB interface. TM1638 is very similiar to GN6932 and TM1637. See [this topic](https://www.elektroda.com/rtvforum/viewtopic.php?p=20553628#20553628) for details. | +| HT16K33 | Driver for 16-segment LED display with I2C. See [protocol explanation](https://www.elektroda.pl/rtvforum/topic3984616.html) | | SHT3X | Humidity/temperature sensor. See [SHT Sensor tutorial topic here](https://www.elektroda.com/rtvforum/topic3958369.html), also see [this sensor teardown](https://www.elektroda.com/rtvforum/topic3945688.html) | | SGP | SGP Air Quality sensor with I2C interface. | | ShiftRegister | ShiftRegisterShiftRegisterShiftRegisterShiftRegister | diff --git a/docs/flags.md b/docs/flags.md index 42f805d5c..44e85656a 100644 --- a/docs/flags.md +++ b/docs/flags.md @@ -46,3 +46,4 @@ Do not add anything here, as it will overwritten with next rebuild. | 38 | [Power] Set power and current to zero if all relays are open | | 39 | [MQTT] [Debug] Publish all channels (don't enable it, it will be publish all 64 possible channels on connect) | | 40 | [MQTT] Use kWh unit for energy consumption (total, last hour, today) instead of Wh | +| 41 | [BTN] Ignore all button events (aka child lock) | diff --git a/docs/ioRoles.md b/docs/ioRoles.md index b4b3e27e3..3cefba0e5 100644 --- a/docs/ioRoles.md +++ b/docs/ioRoles.md @@ -81,4 +81,6 @@ Do not add anything here, as it will overwritten with next rebuild. | TM1638_DAT | QQQ | | TM1638_STB | QQQ | | BAT_Relay_n | Like BAT_Relay, but inversed. See [battery driver topic here](https://www.elektroda.com/rtvforum/topic3959103.html) | +| KP18058_CLK | QQQ | +| KP18058_DAT | QQQ | | Total_Options | Current total number of available IOR roles | diff --git a/docs/json/channelTypes.json b/docs/json/channelTypes.json index 27252fb47..fbac34428 100644 --- a/docs/json/channelTypes.json +++ b/docs/json/channelTypes.json @@ -303,6 +303,14 @@ "file": "new_pins.h", "driver": "" }, + { + "name": "Illuminance", + "title": "TODO", + "descr": "Illuminance in Lux", + "enum": "ChType_Illuminance", + "file": "new_pins.h", + "driver": "" + }, { "name": "Max", "title": "TODO", diff --git a/docs/json/commands.json b/docs/json/commands.json index eb6022f93..648f4b5ee 100644 --- a/docs/json/commands.json +++ b/docs/json/commands.json @@ -512,6 +512,15 @@ "requires": "", "examples": "" }, + { + "name": "ExitSimulator", + "args": "", + "descr": "[SIMULATOR ONLY] Exits the application instance", + "fn": "CMD_ExitSimulator", + "file": "cmnds/cmd_simulatorOnly.c", + "requires": "", + "examples": "" + }, { "name": "fakeTuyaPacket", "args": "[HexString]", @@ -611,6 +620,60 @@ "requires": "", "examples": "" }, + { + "name": "HT16K33_Blink", + "args": "HT16K33_Blink", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_ht16k33.c", + "requires": "", + "examples": "" + }, + { + "name": "HT16K33_Brightness", + "args": "HT16K33_Brightness", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_ht16k33.c", + "requires": "", + "examples": "" + }, + { + "name": "HT16K33_Char", + "args": "HT16K33_Char", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_ht16k33.c", + "requires": "", + "examples": "" + }, + { + "name": "HT16K33_Print", + "args": "HT16K33_Print", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_ht16k33.c", + "requires": "", + "examples": "" + }, + { + "name": "HT16K33_Raw", + "args": "HT16K33_Raw", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_ht16k33.c", + "requires": "", + "examples": "" + }, + { + "name": "HT16K33_Test", + "args": "HT16K33_Test", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_ht16k33.c", + "requires": "", + "examples": "" + }, { "name": "if", "args": "[Condition]['then'][CommandA]['else'][CommandB]", @@ -647,6 +710,24 @@ "requires": "", "examples": "" }, + { + "name": "KP18058_Map", + "args": "[Ch0][Ch1][Ch2][Ch3][Ch4]", + "descr": "Maps KP18058_Map RGBCW values to given indices of KP18058 channels. This is because KP18058 channels order is not the same for some devices. Some devices are using RGBCW order and some are using GBRCW, etc, etc. Example usage: KP18058_Map 0 1 2 3 4", + "fn": "KP18058_Map", + "file": "driver/drv_sm2235.c", + "requires": "", + "examples": "" + }, + { + "name": "KP18058_RGBCW", + "args": "[HexColor]", + "descr": "Don't use it. It's for direct access of KP18058 driver. You don't need it because LED driver automatically calls it, so just use led_basecolor_rgb", + "fn": "KP18058_RGBCW", + "file": "driver/drv_bp5758d.c", + "requires": "", + "examples": "" + }, { "name": "lcd_clear", "args": "", @@ -1088,6 +1169,51 @@ "requires": "", "examples": "" }, + { + "name": "MCP9808_Adr", + "args": "MCP9808_Adr", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_mcp9808.c", + "requires": "", + "examples": "" + }, + { + "name": "MCP9808_AlertMin", + "args": "MCP9808_AlertMin", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_mcp9808.c", + "requires": "", + "examples": "" + }, + { + "name": "MCP9808_AlertRange", + "args": "MCP9808_AlertRange", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_mcp9808.c", + "requires": "", + "examples": "" + }, + { + "name": "MCP9808_Calibrate", + "args": "MCP9808_Calibrate", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_mcp9808.c", + "requires": "", + "examples": "" + }, + { + "name": "MCP9808_Cycle", + "args": "MCP9808_cycle", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_mcp9808.c", + "requires": "", + "examples": "" + }, { "name": "MqttClient", "args": "[ValueString]", @@ -1423,9 +1549,9 @@ }, { "name": "sendPOST", - "args": "CMD_SendPOST", - "descr": "", - "fn": "NULL);", + "args": "[TargetURL] [HTTP Port] [Content Type] [Post Content]", + "descr": "Sends a HTTP POST request to target URL. Arguments can contain variable expansion.", + "fn": "CMD_SendPOST", "file": "cmnds/cmd_send.c", "requires": "", "examples": "" @@ -1755,37 +1881,28 @@ "examples": "" }, { - "name": "SM16703P_Send", - "args": "", - "descr": "NULL", - "fn": "SM16703P_Send_Cmd", + "name": "SM16703P_Init", + "args": "SM16703P_Start", + "descr": "", + "fn": "NULL);", "file": "driver/drv_sm16703P.c", "requires": "", "examples": "" }, { - "name": "SM16703P_Test", - "args": "", - "descr": "qq", - "fn": "SM16703P_Test", - "file": "driver/drv_ucs1912.c", - "requires": "", - "examples": "" - }, - { - "name": "SM16703P_Test_3xOne", - "args": "", - "descr": "NULL", - "fn": "SM16703P_Test_3xOne", + "name": "SM16703P_SetPixel", + "args": "SM16703P_CMD_setPixel", + "descr": "", + "fn": "NULL);", "file": "driver/drv_sm16703P.c", "requires": "", "examples": "" }, { - "name": "SM16703P_Test_3xZero", - "args": "", - "descr": "NULL", - "fn": "SM16703P_Test_3xZero", + "name": "SM16703P_Start", + "args": "SM16703P_StartTX", + "descr": "", + "fn": "NULL);", "file": "driver/drv_sm16703P.c", "requires": "", "examples": "" @@ -2177,6 +2294,15 @@ "requires": "", "examples": "" }, + { + "name": "tuyaMcu_sendColor", + "args": "Cmd_TuyaMCU_SendColor", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_tuyaMCU.c", + "requires": "", + "examples": "" + }, { "name": "tuyaMcu_sendCurTime", "args": "", @@ -2258,6 +2384,15 @@ "requires": "", "examples": "" }, + { + "name": "tuyaMcu_setupLED", + "args": "Cmd_TuyaMCU_SetupLED", + "descr": "", + "fn": "NULL);", + "file": "driver/drv_tuyaMCU.c", + "requires": "", + "examples": "" + }, { "name": "tuyaMcu_testSendTime", "args": "", diff --git a/docs/json/constants.json b/docs/json/constants.json index 21af26723..5eb5ba948 100644 --- a/docs/json/constants.json +++ b/docs/json/constants.json @@ -29,6 +29,18 @@ "descr": "Provides channel access, as above.", "requires": "" }, + { + "name": "$FLAG**", + "title": "$FLAG**", + "descr": "Provides flag access, as above.", + "requires": "" + }, + { + "name": "$FLAG*", + "title": "$FLAG*", + "descr": "Provides flag access, as above.", + "requires": "" + }, { "name": "$led_dimmer", "title": "$led_dimmer", @@ -101,6 +113,12 @@ "descr": "Current value of power from energy metering chip", "requires": "" }, + { + "name": "$energy", + "title": "$energy", + "descr": "Current value of energy counter from energy metering chip", + "requires": "" + }, { "name": "$day", "title": "$day", diff --git a/docs/json/drivers.json b/docs/json/drivers.json index c45397609..23551db81 100644 --- a/docs/json/drivers.json +++ b/docs/json/drivers.json @@ -89,6 +89,12 @@ "descr": "SSDP is a discovery protocol, so BK devices can show up in, for example, Windows network section", "requires": "" }, + { + "name": "DGR", + "title": "TODO", + "descr": "Tasmota Device groups driver. See [forum example](https://www.elektroda.com/rtvforum/topic3925472.html) and TODO-video tutorial (will post on YT soon)", + "requires": "" + }, { "name": "Wemo", "title": "TODO", @@ -96,9 +102,9 @@ "requires": "" }, { - "name": "DGR", + "name": "Hue", "title": "TODO", - "descr": "Tasmota Device groups driver. See [forum example](https://www.elektroda.com/rtvforum/topic3925472.html) and TODO-video tutorial (will post on YT soon)", + "descr": "Hue emulation for Alexa. You must also start SSDP so it can run, because it depends on SSDP discovery.", "requires": "" }, { @@ -158,13 +164,19 @@ { "name": "KP18068", "title": "TODO", - "descr": "KP18068 I2C LED driver", + "descr": "KP18068 I2C LED driver. Unfinished due to the lack of the information.", + "requires": "" + }, + { + "name": "KP18058", + "title": "TODO", + "descr": "KP18058 I2C LED driver. Working, see reverse-engineering [topic](https://www.elektroda.pl/rtvforum/topic3991620.html)", "requires": "" }, { "name": "MAX72XX", "title": "TODO", - "descr": "MAX72XX LED matrix display driver with font and simple script interface.", + "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)", "requires": "" }, { @@ -185,6 +197,12 @@ "descr": "Driver for 7-segment LED display with DIO/CLK/STB interface. TM1638 is very similiar to GN6932 and TM1637. See [this topic](https://www.elektroda.com/rtvforum/viewtopic.php?p=20553628#20553628) for details.", "requires": "" }, + { + "name": "HT16K33", + "title": "TODO", + "descr": "Driver for 16-segment LED display with I2C. See [protocol explanation](https://www.elektroda.pl/rtvforum/topic3984616.html)", + "requires": "" + }, { "name": "SHT3X", "title": "TODO", diff --git a/docs/json/flags.json b/docs/json/flags.json index a190cca07..4f3c0fdaa 100644 --- a/docs/json/flags.json +++ b/docs/json/flags.json @@ -285,5 +285,12 @@ "title": "todo", "file": "new_pins.h", "descr": "[MQTT] Use kWh unit for energy consumption (total, last hour, today) instead of Wh" + }, + { + "index": "41", + "enum": "OBK_FLAG_BUTTON_DISABLE_ALL", + "title": "todo", + "file": "new_pins.h", + "descr": "[BTN] Ignore all button events (aka child lock)" } ] \ No newline at end of file diff --git a/docs/json/ioRoles.json b/docs/json/ioRoles.json index a8300b287..90a5a624e 100644 --- a/docs/json/ioRoles.json +++ b/docs/json/ioRoles.json @@ -607,6 +607,22 @@ "file": "new_pins.h", "driver": "" }, + { + "name": "KP18058_CLK", + "title": "TODO", + "descr": "QQQ", + "enum": "KP18058_CLK", + "file": "new_pins.h", + "driver": "" + }, + { + "name": "KP18058_DAT", + "title": "TODO", + "descr": "QQQ", + "enum": "KP18058_DAT", + "file": "new_pins.h", + "driver": "" + }, { "name": "Total_Options", "title": "TODO", diff --git a/openBeken_win32_mvsc2017.vcxproj b/openBeken_win32_mvsc2017.vcxproj index a75fd973e..f40fb3e86 100644 --- a/openBeken_win32_mvsc2017.vcxproj +++ b/openBeken_win32_mvsc2017.vcxproj @@ -1,4 +1,4 @@ - + @@ -166,7 +166,7 @@ Disabled .\libs_for_simulator\SDL2-2.24.2\include;.\src\win32\stubs\;.\libs_for_simulator\DevIL-Windows-SDK-1.8.0\include;.\libs_for_simulator\freeglut-MSVC-3.0.0-2.mp\include;.\libs_for_simulator\nativefiledialog\src\include;%(AdditionalIncludeDirectories) - WINDOWS;%(PreprocessorDefinitions);_USE_32BIT_TIME_T + WINDOWS;%(PreprocessorDefinitions);_USE_32BIT_TIME_T;DEBUG true EnableFastChecks MultiThreadedDebugDLL @@ -183,17 +183,17 @@ Disabled .\libs_for_simulator\SDL2-2.24.2\include;.\src\win32\stubs\;.\libs_for_simulator\DevIL-Windows-SDK-1.8.0\include;.\libs_for_simulator\freeglut-MSVC-3.0.0-2.mp\include;.\libs_for_simulator\nativefiledialog\src\include;%(AdditionalIncludeDirectories) - WINDOWS;%(PreprocessorDefinitions);_USE_32BIT_TIME_T;WIN32_LEAN_AND_MEAN;WIN32;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WINDOWS;%(PreprocessorDefinitions);_USE_32BIT_TIME_T;WIN32_LEAN_AND_MEAN;WIN32;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CONSOLE true Default - MultiThreadedDLL + MultiThreaded Level3 EditAndContinue true MachineX86 - .\libs_for_simulator\SDL2-2.24.2\lib\x86;.\libs_for_simulator\DevIL-Windows-SDK-1.8.0\lib\x86\Release;.\libs_for_simulator\freeglut-MSVC-3.0.0-2.mp\lib;.\libs_for_simulator\nativefiledialog\build\lib\Debug\x86 + .\libs_for_simulator\SDL2-2.24.2\lib\x86;.\libs_for_simulator\DevIL-Windows-SDK-1.8.0\lib\x86\Release;.\libs_for_simulator\freeglut-MSVC-3.0.0-2.mp\lib;.\libs_for_simulator\nativefiledialog\build\lib\Release\x86 @@ -298,6 +298,7 @@ true + true @@ -338,6 +339,7 @@ true + true @@ -348,10 +350,13 @@ + + true + true @@ -359,6 +364,7 @@ + true @@ -950,6 +956,7 @@ + @@ -1057,6 +1064,7 @@ + diff --git a/openBeken_win32_mvsc2017.vcxproj.filters b/openBeken_win32_mvsc2017.vcxproj.filters index aafa7ae68..f663fbe16 100644 --- a/openBeken_win32_mvsc2017.vcxproj.filters +++ b/openBeken_win32_mvsc2017.vcxproj.filters @@ -869,6 +869,25 @@ SelfTest + + Drv + + + Drv + + + + Cmd + + + Drv + + + Drv + + + SelfTest + @@ -1273,6 +1292,9 @@ Drv + + Drv + diff --git a/run_without_selfTests.bat b/run_without_selfTests.bat new file mode 100644 index 000000000..b277f7734 --- /dev/null +++ b/run_without_selfTests.bat @@ -0,0 +1 @@ +openBeken_win32.exe -runUnitTests 0 \ No newline at end of file diff --git a/src/cmnds/cmd_eventHandlers.c b/src/cmnds/cmd_eventHandlers.c index 4cf4d12a2..b75326ddf 100644 --- a/src/cmnds/cmd_eventHandlers.c +++ b/src/cmnds/cmd_eventHandlers.c @@ -79,7 +79,7 @@ addChangeHandler NoPingTime > 40 doRelayClick // This will automatically turn off relay after about 2 seconds // NOTE: addRepeatingEvent [RepeatTime] [RepeatCount] -// addChangeHandler Channel0 != 0 addRepeatingEvent 2 1 setChannel 0 0 +addChangeHandler Channel0 != 0 addRepeatingEvent 2 1 setChannel 0 0 AddEventHandler OnClick 0 addChannel 1 -10 0 100 AddEventHandler OnClick 1 addChannel 1 10 0 100 @@ -177,7 +177,7 @@ int EVENT_ParseEventName(const char *s) { return CMD_EVENT_LED_STATE; if (!stricmp(s, "LEDMode")) return CMD_EVENT_LED_MODE; - if(!stricmp(s,"energycounter")) + if(!stricmp(s,"energycounter") || !stricmp(s, "energy")) return CMD_EVENT_CHANGE_CONSUMPTION_TOTAL; if(!stricmp(s,"energycounter_last_hour")) return CMD_EVENT_CHANGE_CONSUMPTION_LAST_HOUR; diff --git a/src/cmnds/cmd_if.c b/src/cmnds/cmd_if.c index b906d7014..09119934d 100644 --- a/src/cmnds/cmd_if.c +++ b/src/cmnds/cmd_if.c @@ -160,6 +160,10 @@ float getChannelValue(const char *s) { int idx = atoi(s + 3); return CHANNEL_Get(idx); } +float getFlagValue(const char *s) { + int idx = atoi(s + 5); + return CFG_HasFlag(idx); +} float getLedDimmer(const char *s) { return LED_GetDimmer(); @@ -210,6 +214,10 @@ float getCurrent(const char *s) { float getPower(const char *s) { return DRV_GetReading(OBK_POWER); } +float getEnergy(const char *s) { + return DRV_GetReading(OBK_CONSUMPTION_TOTAL); +} + float getNTPOn(const char *s) { return NTP_IsTimeSynced(); @@ -262,6 +270,16 @@ const constant_t g_constants[] = { //cnstdetail:"descr":"Provides channel access, as above.", //cnstdetail:"requires":""} {"$CH*", &getChannelValue}, + //cnstdetail:{"name":"$FLAG**", + //cnstdetail:"title":"$FLAG**", + //cnstdetail:"descr":"Provides flag access, as above.", + //cnstdetail:"requires":""} + {"$FLAG**", &getFlagValue}, + //cnstdetail:{"name":"$FLAG*", + //cnstdetail:"title":"$FLAG*", + //cnstdetail:"descr":"Provides flag access, as above.", + //cnstdetail:"requires":""} + {"$FLAG*", &getFlagValue}, //cnstdetail:{"name":"$led_dimmer", //cnstdetail:"title":"$led_dimmer", //cnstdetail:"descr":"Current value of LED dimmer, 0-100 range", @@ -323,6 +341,11 @@ const constant_t g_constants[] = { //cnstdetail:"descr":"Current value of power from energy metering chip", //cnstdetail:"requires":""} {"$power", &getPower}, + //cnstdetail:{"name":"$energy", + //cnstdetail:"title":"$energy", + //cnstdetail:"descr":"Current value of energy counter from energy metering chip", + //cnstdetail:"requires":""} + {"$energy", &getEnergy}, //cnstdetail:{"name":"$day", //cnstdetail:"title":"$day", //cnstdetail:"descr":"Current weekday from NTP", diff --git a/src/cmnds/cmd_local.h b/src/cmnds/cmd_local.h index 6cc836cef..c3936b0a6 100644 --- a/src/cmnds/cmd_local.h +++ b/src/cmnds/cmd_local.h @@ -19,7 +19,6 @@ int get_cmd(const char *s, char *dest, int maxlen, int stripnum); float CMD_EvaluateExpression(const char *s, const char *stop); commandResult_t CMD_If(const void *context, const char *cmd, const char *args, int cmdFlags); void CMD_ExpandConstantsWithinString(const char *in, char *out, int outLen); -const char *CMD_ExpandConstant(const char *s, const char *stop, float *out); #endif // __CMD_LOCAL_H__ diff --git a/src/cmnds/cmd_newLEDDriver.c b/src/cmnds/cmd_newLEDDriver.c index 54eff5db9..e08d72286 100644 --- a/src/cmnds/cmd_newLEDDriver.c +++ b/src/cmnds/cmd_newLEDDriver.c @@ -107,9 +107,18 @@ void LED_ResetGlobalVariablesToDefaults() { bool LED_IsLedDriverChipRunning() { +#ifndef PLATFORM_W600 +#ifndef OBK_DISABLE_ALL_DRIVERS + if (TuyaMCU_IsLEDRunning()) { + return true; + } +#endif +#endif #ifndef OBK_DISABLE_ALL_DRIVERS return DRV_IsRunning("SM2135") || DRV_IsRunning("BP5758D") - || DRV_IsRunning("TESTLED") || DRV_IsRunning("SM2235") || DRV_IsRunning("BP1658CJ"); + || DRV_IsRunning("TESTLED") || DRV_IsRunning("SM2235") || DRV_IsRunning("BP1658CJ") + || DRV_IsRunning("KP18058") + ; #else return false; #endif @@ -253,6 +262,9 @@ void LED_I2CDriver_WriteRGBCW(float* finalRGBCW) { if (DRV_IsRunning("SM2235")) { SM2235_Write(finalRGBCW); } + if (DRV_IsRunning("KP18058")) { + KP18058_Write(finalRGBCW); + } #endif } void LED_RunOnEverySecond() { @@ -552,7 +564,12 @@ void apply_smart_light() { #ifndef OBK_DISABLE_ALL_DRIVERS DRV_DGR_OnLedFinalColorsChange(baseRGBCW); #endif - +#ifndef PLATFORM_W600 +#ifndef OBK_DISABLE_ALL_DRIVERS + TuyaMCU_OnRGBCWChange(finalColors, g_lightEnableAll, g_lightMode, g_brightness0to100*0.01f, LED_GetTemperature0to1Range()); +#endif +#endif + // I am not sure if it's the best place to do it // NOTE: this will broadcast MQTT only if a flag is set sendFullRGBCW_IfEnabled(); diff --git a/src/cmnds/cmd_public.h b/src/cmnds/cmd_public.h index 2ff498f70..b4eb1ed4a 100644 --- a/src/cmnds/cmd_public.h +++ b/src/cmnds/cmd_public.h @@ -44,6 +44,7 @@ commandResult_t CMD_ExecuteCommandArgs(const char* cmd, const char* args, int cm // Please remember to free the returned string char* CMD_ExpandingStrdup(const char* in); commandResult_t CMD_CreateAliasHelper(const char *alias, const char *ocmd); +const char *CMD_ExpandConstant(const char *s, const char *stop, float *out); enum EventCode { CMD_EVENT_NONE, diff --git a/src/cmnds/cmd_send.c b/src/cmnds/cmd_send.c index 50d1e5361..6140e0ef9 100644 --- a/src/cmnds/cmd_send.c +++ b/src/cmnds/cmd_send.c @@ -59,10 +59,13 @@ int CMD_InitSendCommands() { //cmddetail:"examples":""} CMD_RegisterCommand("sendGet", CMD_SendGET, NULL); - //cmddetail:{"name":"sendPost","args":"[TargetURL] [HTTP Port] [Content Type] [Post Content]", - //cmddetail:"descr":"Sends a HTTP POST request to target URL", + // TODO example + // SendPost "http://192.168.0.1/write?db=energy" 8086 "application/octet-stream" "current,clientid=A0:92:08:CB:41:E1 value=$current"" + + //cmddetail:{"name":"sendPOST","args":"[TargetURL] [HTTP Port] [Content Type] [Post Content]", + //cmddetail:"descr":"Sends a HTTP POST request to target URL. Arguments can contain variable expansion.", //cmddetail:"fn":"CMD_SendPOST","file":"cmnds/cmd_send.c","requires":"", - //cmddetail:"examples":"SendPost ""http://192.168.0.1/write?db=energy"" 8086 ""application/octet-stream"" ""current,clientid=A0:92:08:CB:41:E1 value=$current"""} + //cmddetail:"examples":""} CMD_RegisterCommand("sendPOST", CMD_SendPOST, NULL); //CMD_RegisterCommand("testPost", CMD_TestPOST, NULL); diff --git a/src/cmnds/cmd_simulatorOnly.c b/src/cmnds/cmd_simulatorOnly.c new file mode 100644 index 000000000..d59c0dde1 --- /dev/null +++ b/src/cmnds/cmd_simulatorOnly.c @@ -0,0 +1,30 @@ +#include "../new_pins.h" +#include "../new_cfg.h" +#include "../logging/logging.h" +#include "../obk_config.h" + +#if WINDOWS + +#include +#include "cmd_local.h" + +// exits Windows application +static commandResult_t CMD_ExitSimulator(const void* context, const char* cmd, const char* args, int cmdFlags) { + Tokenizer_TokenizeString(args, 0); + + exit(0); + + return CMD_RES_OK; +} + + +void CMD_InitSimulatorOnlyCommands() { + //cmddetail:{"name":"ExitSimulator","args":"", + //cmddetail:"descr":"[SIMULATOR ONLY] Exits the application instance", + //cmddetail:"fn":"CMD_ExitSimulator","file":"cmnds/cmd_simulatorOnly.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("ExitSimulator", CMD_ExitSimulator, NULL); +} + +#endif WINDOWS + diff --git a/src/cmnds/cmd_tokenizer.c b/src/cmnds/cmd_tokenizer.c index e836496b8..3f87f5230 100644 --- a/src/cmnds/cmd_tokenizer.c +++ b/src/cmnds/cmd_tokenizer.c @@ -52,6 +52,9 @@ int Tokenizer_GetArgsCount() { bool Tokenizer_IsArgInteger(int i) { if(i >= g_numArgs) return false; + if (*g_args[i] == '$') { + return true; + } return strIsInteger(g_args[i]); } const char *Tokenizer_GetArg(int i) { diff --git a/src/driver/drv_bl_shared.c b/src/driver/drv_bl_shared.c index 6db5f28f7..576f6d4a7 100644 --- a/src/driver/drv_bl_shared.c +++ b/src/driver/drv_bl_shared.c @@ -624,6 +624,10 @@ void BL_ProcessUpdate(float voltage, float current, float power, if (energyCounterMinutes != NULL) { stats = cJSON_CreateArray(); + // WARNING - it causes HA problems? + // See: https://github.com/openshwprojects/OpenBK7231T_App/issues/870 + // Basically HA has 256 chars state limit? + // Wait, no, it's over 256 even without samples? for(i = 0; i < energyCounterSampleCount; i++) { cJSON_AddItemToArray(stats, cJSON_CreateNumber(energyCounterMinutes[i])); diff --git a/src/driver/drv_chargingLimit.c b/src/driver/drv_chargingLimit.c new file mode 100644 index 000000000..43cb9044e --- /dev/null +++ b/src/driver/drv_chargingLimit.c @@ -0,0 +1,107 @@ +#include "../new_common.h" +#include "../new_pins.h" +#include "../new_cfg.h" +// Commands register, execution API and cmd tokenizer +#include "../cmnds/cmd_public.h" +#include "../mqtt/new_mqtt.h" +#include "../logging/logging.h" +#include "drv_local.h" +#include "../hal/hal_pins.h" + +static int chl_targetChannel = -1; +static int chl_targetChannelStartValue = -1; +static int chl_targetChannelMaxDelta = -1; +static int chl_timeLeftSeconds = -1; +static char *chl_commandToRun = 0; +static int chl_lastDelteForDisplay = -1; + +// startDriver ChargingLimit +// chSetupLimit [limitChannelIndex] [maxAllowedLimitChannelDelta] [timeoutOr-1] [commandToRun] +// chSetupLimit 5 5000 3600 "POWER OFF" +// or: +// alias myOff backlog POWER OFF; and smth else; and delse; +// chSetupLimit 5 5000 3600 myOff +commandResult_t ChargingLimit_SetupCommand(const void* context, const char* cmd, const char* args, int cmdFlags) { + const char *newCmd; + + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES); + // following check must be done after 'Tokenizer_TokenizeString', + // so we know arguments count in Tokenizer. 'cmd' argument is + // only for warning display + if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + + chl_targetChannel = Tokenizer_GetArgInteger(0); + chl_targetChannelStartValue = CHANNEL_Get(chl_targetChannel); + chl_targetChannelMaxDelta = Tokenizer_GetArgInteger(1); + chl_timeLeftSeconds = Tokenizer_GetArgInteger(2); + newCmd = Tokenizer_GetArg(3); + if (chl_commandToRun != 0 && !strcmp(chl_commandToRun, newCmd)) { + // no change, avoid free + malloc + } + else { + if (chl_commandToRun) + free(chl_commandToRun); + chl_commandToRun = strdup(newCmd); + } + + return CMD_RES_OK; +} +void ChargingLimit_Init() { + + CMD_RegisterCommand("chSetupLimit", ChargingLimit_SetupCommand, NULL); +} +void ChargingLimit_OnLimitReached(bool bTimedOut) { + // cast event + CMD_ExecuteCommand(chl_commandToRun, 0); + // reset variables + chl_targetChannel = -1; + chl_targetChannelStartValue = -1; + chl_targetChannelMaxDelta = -1; + chl_timeLeftSeconds = -1; + // do not reset command because we may want to reuse the strdup allocation +} +void ChargingLimit_OnEverySecond() { + int newValue; + + // if off + if (chl_targetChannel == -1) + return; + // tick time + if (chl_timeLeftSeconds != -1) { + chl_timeLeftSeconds--; + if (chl_timeLeftSeconds <= 0) { + ChargingLimit_OnLimitReached(true); + return; + } + } + // check channel + newValue = CHANNEL_Get(chl_targetChannel); + chl_lastDelteForDisplay = newValue - chl_targetChannelStartValue; + // absolute + if (chl_lastDelteForDisplay < 0) + chl_lastDelteForDisplay = -chl_lastDelteForDisplay; + // has exceed? + if (chl_lastDelteForDisplay > chl_targetChannelMaxDelta) { + ChargingLimit_OnLimitReached(false); + } +} + +void ChargingLimit_AppendInformationToHTTPIndexPage(http_request_t* request) +{ + if (chl_targetChannel == -1) { + hprintf255(request, "

Charging limit reached

"); + } + else { + hprintf255(request, "

Charging limit on for channel %i - %i/%i, time left %i s

", + chl_targetChannel, + chl_lastDelteForDisplay, chl_targetChannelMaxDelta, chl_timeLeftSeconds); + } +} + + + + + + diff --git a/src/driver/drv_ht16k33.c b/src/driver/drv_ht16k33.c new file mode 100644 index 000000000..a15391022 --- /dev/null +++ b/src/driver/drv_ht16k33.c @@ -0,0 +1,303 @@ +// NOTE: based on https://github.com/RobTillaart/HT16K33.git MIT code +#include "../new_common.h" +#include "../new_pins.h" +#include "../new_cfg.h" +// Commands register, execution API and cmd tokenizer +#include "../cmnds/cmd_public.h" +#include "../mqtt/new_mqtt.h" +#include "../logging/logging.h" +#include "drv_local.h" +#include "drv_ht16k33.h" +#include "../hal/hal_pins.h" + +static softI2C_t g_softI2C; +static byte g_addr = 0xE0; + + +uint8_t _bright = 0x0F; + +void HT16K33_WriteCmd(byte b) { + Soft_I2C_Start(&g_softI2C, g_addr); + Soft_I2C_WriteByte(&g_softI2C, b); + Soft_I2C_Stop(&g_softI2C); +} + +void HT16K33_brightness(uint8_t value) +{ + _bright = value; + if (_bright > 0x0F) + _bright = 0x0F; + HT16K33_WriteCmd(HT16K33_BRIGHTNESS | _bright); +} +void HT16K33_displayOn() +{ + HT16K33_WriteCmd(HT16K33_ON); + HT16K33_WriteCmd(HT16K33_DISPLAYON); + HT16K33_brightness(_bright); +} + +// +// HEX codes 7 segment +// Currently unused! +// +// 01 +// 20 02 +// 40 +// 10 04 +// 08 +// +#if 0 +static const uint8_t charMap7seg[] = { + + 0x3F, // 0 + 0x06, // 1 + 0x5B, // 2 + 0x4F, // 3 + 0x66, // 4 + 0x6D, // 5 + 0x7D, // 6 + 0x07, // 7 + 0x7F, // 8 + 0x6F, // 9 + 0x77, // A + 0x7C, // B + 0x39, // C + 0x5E, // D + 0x79, // E + 0x71, // F + 0x00, // space + 0x40, // minus + 0x61, // TOP_C + 0x63, // degree � +}; +#endif +unsigned short convert16seg(char c) +{ + unsigned short c2; + switch (c) + { + case ' ': c2 = 0x0000; break; + case '.': c2 = 0x4000; break; + case '+': c2 = 0x12C0; break; + case '-': c2 = 0x00C0; break; + case '*': c2 = 0x3FC0; break; + case '/': c2 = 0x0C00; break; + case '=': c2 = 0x00C8; break; + case '>': c2 = 0x0900; break; + case '<': c2 = 0x2400; break; + case '[': c2 = 0x0039; break; + case ']': c2 = 0x000F; break; + //--------------------------- + case '0': c2 = 0x0C3F; break; + case '1': c2 = 0x0406; break; + case '2': c2 = 0x00DB; break; + case '3': c2 = 0x008F; break; + case '4': c2 = 0x00E6; break; + case '5': c2 = 0x00ED; break; + case '6': c2 = 0x00FD; break; + case '7': c2 = 0x0007; break; + case '8': c2 = 0x00FF; break; + case '9': c2 = 0x00EF; break; + //--------------------------- + case 'A': c2 = 0x00F7; break; + case 'B': c2 = 0x128F; break; + case 'C': c2 = 0x0039; break; + case 'D': c2 = 0x120F; break; + case 'E': c2 = 0x00F9; break; + case 'F': c2 = 0x00F1; break; + case 'G': c2 = 0x00BD; break; + case 'H': c2 = 0x00F6; break; + case 'I': c2 = 0x1209; break; + case 'J': c2 = 0x001E; break; + case 'K': c2 = 0x2470; break; + case 'L': c2 = 0x0038; break; + case 'M': c2 = 0x0536; break; + case 'N': c2 = 0x2136; break; + case 'O': c2 = 0x003F; break; + case 'P': c2 = 0x00F3; break; + case 'Q': c2 = 0x203F; break; + case 'R': c2 = 0x20F3; break; + case 'S': c2 = 0x018D; break; + case 'T': c2 = 0x1201; break; + case 'U': c2 = 0x003E; break; + case 'V': c2 = 0x0C30; break; + case 'W': c2 = 0x2836; break; + case 'X': c2 = 0x2D00; break; + case 'Y': c2 = 0x1500; break; + case 'Z': c2 = 0x0C09; + } + return c2; +} + + +void HT16K33_writePos(uint8_t pos, unsigned short mask) +{ + Soft_I2C_Start(&g_softI2C, g_addr); + Soft_I2C_WriteByte(&g_softI2C, pos*2); + Soft_I2C_WriteByte(&g_softI2C, mask & 0x00FF); + Soft_I2C_WriteByte(&g_softI2C, (mask & 0xFF00) >> 8); + Soft_I2C_Stop(&g_softI2C); +} +void HT16K33_display(const char *txt, uint8_t point) +{ + int i = 0; + unsigned short code; + + while (*txt) { + code = convert16seg(*txt); + + HT16K33_writePos(i,code); + txt++; + i++; + } +} +void HT16K33_displayOff() +{ + HT16K33_WriteCmd(HT16K33_DISPLAYOFF); + HT16K33_WriteCmd(HT16K33_STANDBY); +} + +void HT16K33_displayClear() +{ + HT16K33_display(" ",4); + //HT16K33_displayColon(false); +} +commandResult_t HT16K33_Test(const void* context, const char* cmd, const char* args, int cmdFlags) { + + + g_softI2C.pin_clk = 26; + g_softI2C.pin_data = 24; + + + Soft_I2C_PreInit(&g_softI2C); + + rtos_delay_milliseconds(25); + + HT16K33_displayOn(); + rtos_delay_milliseconds(25); + //HT16K33_displayClear(); + rtos_delay_milliseconds(25); + HT16K33_display("1234", 4); + rtos_delay_milliseconds(25); + HT16K33_brightness(8); + + return CMD_RES_OK; +} +commandResult_t HT16K33_Print(const void* context, const char* cmd, const char* args, int cmdFlags) { + + Tokenizer_TokenizeString(args, 0); + + if (Tokenizer_GetArgsCount() < 1) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + const char *s = Tokenizer_GetArg(0); + + HT16K33_display(s, 4); + + return CMD_RES_OK; +} + +commandResult_t HT16K33_Char(const void* context, const char* cmd, const char* args, int cmdFlags) { + int pos, val; + + Tokenizer_TokenizeString(args, 0); + + if (Tokenizer_GetArgsCount() < 2) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + pos = Tokenizer_GetArgInteger(0); + val = Tokenizer_GetArgInteger(1); + + HT16K33_writePos(pos, convert16seg(val)); + + return CMD_RES_OK; +} +commandResult_t HT16K33_Raw(const void* context, const char* cmd, const char* args, int cmdFlags) { + int pos, val; + + Tokenizer_TokenizeString(args, 0); + + if (Tokenizer_GetArgsCount() < 2) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + pos = Tokenizer_GetArgInteger(0); + val = Tokenizer_GetArgInteger(1); + + HT16K33_writePos(pos, val); + + return CMD_RES_OK; +} +commandResult_t HT16K33_Brightness(const void* context, const char* cmd, const char* args, int cmdFlags) { + int val; + + Tokenizer_TokenizeString(args, 0); + + if (Tokenizer_GetArgsCount() < 1) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + val = Tokenizer_GetArgInteger(0); + + HT16K33_brightness(val); + + return CMD_RES_OK; +} +commandResult_t HT16K33_Blink(const void* context, const char* cmd, const char* args, int cmdFlags) { + int type; + + Tokenizer_TokenizeString(args, 0); + + if (Tokenizer_GetArgsCount() < 1) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + type = Tokenizer_GetArgInteger(0); + + if (type == 0) { + HT16K33_WriteCmd(HT16K33_BLINKOFF); + } + else if (type == 1) { + HT16K33_WriteCmd(HT16K33_BLINKON0_5HZ); + } + else if (type == 2) { + HT16K33_WriteCmd(HT16K33_BLINKON1HZ); + } + else { + HT16K33_WriteCmd(HT16K33_BLINKON2HZ); + } + + return CMD_RES_OK; +} +// backlog startDriver HT16K33; HT16K33_Test +// backlog startDriver HT16K33; HT16K33_Print Help +void HT16K33_Init() { + + //cmddetail:{"name":"HT16K33_Test","args":"HT16K33_Test", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_ht16k33.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("HT16K33_Test", HT16K33_Test, NULL); + //cmddetail:{"name":"HT16K33_Char","args":"HT16K33_Char", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_ht16k33.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("HT16K33_Char", HT16K33_Char, NULL); + //cmddetail:{"name":"HT16K33_Raw","args":"HT16K33_Raw", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_ht16k33.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("HT16K33_Raw", HT16K33_Raw, NULL); + //cmddetail:{"name":"HT16K33_Print","args":"HT16K33_Print", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_ht16k33.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("HT16K33_Print", HT16K33_Print, NULL); + //cmddetail:{"name":"HT16K33_Brightness","args":"HT16K33_Brightness", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_ht16k33.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("HT16K33_Brightness", HT16K33_Brightness, NULL); + //cmddetail:{"name":"HT16K33_Blink","args":"HT16K33_Blink", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_ht16k33.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("HT16K33_Blink", HT16K33_Blink, NULL); +} diff --git a/src/driver/drv_ht16k33.h b/src/driver/drv_ht16k33.h new file mode 100644 index 000000000..5481aa12f --- /dev/null +++ b/src/driver/drv_ht16k33.h @@ -0,0 +1,42 @@ + +// Characters +#define HT16K33_0 0 +#define HT16K33_1 1 +#define HT16K33_2 2 +#define HT16K33_3 3 +#define HT16K33_4 4 +#define HT16K33_5 5 +#define HT16K33_6 6 +#define HT16K33_7 7 +#define HT16K33_8 8 +#define HT16K33_9 9 +#define HT16K33_A 10 +#define HT16K33_B 11 +#define HT16K33_C 12 +#define HT16K33_D 13 +#define HT16K33_E 14 +#define HT16K33_F 15 +#define HT16K33_SPACE 16 +#define HT16K33_MINUS 17 +#define HT16K33_TOP_C 18 // c +#define HT16K33_DEGREE 19 // +#define HT16K33_NONE 99 + + +// Commands +#define HT16K33_ON 0x21 // 0 = off 1 = on +#define HT16K33_STANDBY 0x20 // bit xxxxxxx0 + +// bit pattern 1000 0xxy +// y = display on / off +// xx = 00=off 01=2Hz 10 = 1Hz 11 = 0.5Hz +#define HT16K33_DISPLAYON 0x81 +#define HT16K33_DISPLAYOFF 0x80 +#define HT16K33_BLINKON0_5HZ 0x87 +#define HT16K33_BLINKON1HZ 0x85 +#define HT16K33_BLINKON2HZ 0x83 +#define HT16K33_BLINKOFF 0x81 + +// bit pattern 1110 xxxx +// xxxx = 0000 .. 1111 (0 - F) +#define HT16K33_BRIGHTNESS 0xE0 diff --git a/src/driver/drv_httpButtons.c b/src/driver/drv_httpButtons.c index 9cac73c13..69e1bebfb 100644 --- a/src/driver/drv_httpButtons.c +++ b/src/driver/drv_httpButtons.c @@ -87,11 +87,17 @@ setButtonLabel 1 "Set Red 50% brightness" setButtonCommand 1 "backlog led_basecolor_rgb FF0000; led_dimmer 50; led_enableAll 1" //setButtonColor 1 "blue" - - - - */ +// Usage for making LFS page link : +//startDriver httpButtons +//setButtonEnabled 0 1 +//setButtonLabel 0 "Open Config" +//setButtonCommand 0 "*/api/lfs/cfg.html" +//setButtonColor 0 "#FF0000" + + + + @@ -114,6 +120,7 @@ void DRV_HTTPButtons_ProcessChanges(http_request_t *request) { void DRV_HTTPButtons_AddToHtmlPage(http_request_t *request) { int i; const char *c; + const char *action; for (i = 0; i < g_buttonCount; i++) { httpButton_t *bt = g_buttons[i]; @@ -126,13 +133,22 @@ void DRV_HTTPButtons_AddToHtmlPage(http_request_t *request) { hprintf255(request, ""); - c = ""; + c = ""; if (!bt->color[0]) { c = "bgrn"; } + + action = bt->command; + poststr(request, "
"); + } else { + poststr(request, "index"); + poststr(request, "\">"); + hprintf255(request, "", i); + } - poststr(request, ""); - hprintf255(request, "", i); hprintf255(request, "color[0]) { hprintf255(request, "style = \"background-color:%s;\" ",bt->color); diff --git a/src/driver/drv_hue.c b/src/driver/drv_hue.c new file mode 100644 index 000000000..2efad62ab --- /dev/null +++ b/src/driver/drv_hue.c @@ -0,0 +1,252 @@ +#include "../new_common.h" +#include "../new_pins.h" +#include "../new_cfg.h" +// Commands register, execution API and cmd tokenizer +#include "../cmnds/cmd_public.h" +#include "../mqtt/new_mqtt.h" +#include "../logging/logging.h" +#include "../hal/hal_pins.h" +#include "../hal/hal_wifi.h" +#include "drv_public.h" +#include "drv_local.h" +#include "drv_ssdp.h" +#include "../httpserver/new_http.h" + +// Hue driver for Alexa, requiring btsimonh's SSDP to work +// Based on Tasmota approach +// The procedure is following: +// 1. first MSEARCH over UDP is done +// 2. then obk replies to MSEARCH with page details +// 3. then alexa accesses our XML pages here with GET +// 4. and can change the binary state (0 or 1) with POST + +static char *buffer_out = 0; +static char *g_serial = 0; +static char *g_userID = 0; +static char *g_uid = 0; +static char *g_bridgeID = 0; +static int outBufferLen = 0; +static int stat_searchesReceived = 0; +static int stat_setupXMLVisits = 0; +// stubs +static int stat_metaServiceXMLVisits = 0; +static int stat_eventsReceived = 0; +static int stat_eventServiceXMLVisits = 0; + + +// ARGUMENTS: first IP, then bridgeID +const char *hue_resp = "HTTP/1.1 200 OK\r\n" + "HOST: 239.255.255.250:1900\r\n" + "CACHE-CONTROL: max-age=100\r\n" + "EXT:\r\n" + "LOCATION: http://%s:80/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.24.0\r\n" // was 1.17 + "hue-bridgeid: %s\r\n"; + +// ARGUMENTS: uuid +const char *hue_resp1 = "ST: upnp:rootdevice\r\n" + "USN: uuid:%s::upnp:rootdevice\r\n" + "\r\n"; + +// ARGUMENTS: uuid and uuid +const char *hue_resp2 = "ST: uuid:%s\r\n" + "USN: uuid:%s\r\n" + "\r\n"; + +// ARGUMENTS: uuid +const char *hue_resp3 = "ST: urn:schemas-upnp-org:device:basic:1\r\n" + "USN: uuid:%s\r\n" + "\r\n"; + +void DRV_HUE_Send_Advert_To(struct sockaddr_in *addr) { + const char *useType; + + if (g_uid == 0) { + // not running + return; + } + + stat_searchesReceived++; + + if (buffer_out == 0) { + outBufferLen = strlen(hue_resp) + 256; + buffer_out = (char*)malloc(outBufferLen); + } + { + // ARGUMENTS: first IP, then bridgeID + snprintf(buffer_out, outBufferLen, hue_resp, HAL_GetMyIPString(), g_bridgeID); + + addLogAdv(LOG_ALL, LOG_FEATURE_HTTP, "HUE - Sending[0] %s", buffer_out); + DRV_SSDP_SendReply(addr, buffer_out); + } + { + // ARGUMENTS: uuid + snprintf(buffer_out, outBufferLen, hue_resp1, g_uid); + + addLogAdv(LOG_ALL, LOG_FEATURE_HTTP, "HUE - Sending[1] %s", buffer_out); + DRV_SSDP_SendReply(addr, buffer_out); + } + { + // ARGUMENTS: uuid and uuid + snprintf(buffer_out, outBufferLen, hue_resp2, g_uid, g_uid); + + addLogAdv(LOG_ALL, LOG_FEATURE_HTTP, "HUE - Sending[2] %s", buffer_out); + DRV_SSDP_SendReply(addr, buffer_out); + } + { + // ARGUMENTS: uuid + snprintf(buffer_out, outBufferLen, hue_resp3, g_uid); + + addLogAdv(LOG_ALL, LOG_FEATURE_HTTP, "HUE - Sending[3] %s", buffer_out); + DRV_SSDP_SendReply(addr, buffer_out); + } +} + + +void HUE_AppendInformationToHTTPIndexPage(http_request_t* request) { + hprintf255(request, "

HUE: searches %i, setup %i, events %i, mService %i, event %i

", + stat_searchesReceived, stat_setupXMLVisits, stat_eventsReceived, stat_metaServiceXMLVisits, stat_eventServiceXMLVisits); + +} + +const char *g_hue_setup_1 = "" +"" +"" +"1" +"0" +"" +"http://"; +// IP ADDR HERE +const char *g_hue_setup_2 = ":80/" +"" +"urn:schemas-upnp-org:device:Basic:1" +"Amazon-Echo-HA-Bridge ("; +// IP ADDR HERE +const char *g_hue_setup_3 = ")" +"Royal Philips Electronics" +"http://www.philips.com" +"Philips hue Personal Wireless Lighting" +"Philips hue bridge 2012" +"929000226503" +""; +// SERIAL here +const char *g_hue_setup_4 = "" +"uuid:"; +// UID HERE +const char *g_hue_setup_5 = "" + "" + "\r\n" + "\r\n"; + +static int HUE_Setup(http_request_t* request) { + http_setup(request, httpMimeTypeXML); + poststr(request, g_hue_setup_1); + poststr(request, HAL_GetMyIPString()); + poststr(request, g_hue_setup_2); + poststr(request, HAL_GetMyIPString()); + poststr(request, g_hue_setup_3); + poststr(request, g_serial); + poststr(request, g_hue_setup_4); + poststr(request, g_uid); + poststr(request, g_hue_setup_5); + poststr(request, NULL); + + stat_setupXMLVisits++; + + return 0; +} +static int HUE_NotImplemented(http_request_t* request) { + + http_setup(request, httpMimeTypeJson); + poststr(request, "{}"); + poststr(request, NULL); + + return 0; +} +static int HUE_Authentication(http_request_t* request) { + + http_setup(request, httpMimeTypeJson); + hprintf255(request, "[{\"success\":{\"username\":\"%s\"}}]",g_userID); + poststr(request, NULL); + + return 0; +} +static int HUE_Config_Internal(http_request_t* request) { + + poststr(request, "{\"name\":\"Philips hue\",\"mac\":\""); + // TODO: mac + poststr(request, "\",\"dhcp\":true,\"ipaddress\":\""); + // TODO: ip + poststr(request, "\",\"netmask\":\""); + // TODO: mask + poststr(request, "\",\"gateway\":\""); + // TODO: gw + poststr(request, "\",\"proxyaddress\":\"none\",\"proxyport\":0,\"bridgeid\":\""); + // TODO: bridgeid + poststr(request, "\",\"UTC\":\"{dt\",\"whitelist\":{\""); + // TODO: id + poststr(request, "\":{\"last use date\":\""); + // TODO: date + poststr(request, "\",\"create date\":\""); + // TODO: date + poststr(request, "\",\"name\":\"Remote\"}},\"swversion\":\"01041302\",\"apiversion\":\"1.17.0\",\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false},\"linkbutton\":false,\"portalservices\":false}"); + poststr(request, NULL); + + return 0; +} + + + + +static int HUE_GlobalConfig(http_request_t* request) { + + http_setup(request, httpMimeTypeJson); + poststr(request, "{\"lights\":{"); + // TODO: lights + poststr(request, "},\"groups\":{},\"schedules\":{},\"config\":"); + HUE_Config_Internal(request); + poststr(request, "}"); + poststr(request, NULL); + + return 0; +} + + +// http://192.168.0.213/api/username/lights/1/state +// http://192.168.0.213/description.xml +int HUE_APICall(http_request_t* request) { + if (g_uid == 0) { + // not running + return 0; + } + // skip "api/" + const char *api = request->url + 4; + int urlLen = strlen(request->url); + + return 0; +} +// backlog startDriver SSDP; startDriver HUE +// +void HUE_Init() { + char tmp[64]; + unsigned char mac[8]; + + WiFI_GetMacAddress((char*)mac); + // username - + snprintf(tmp, sizeof(tmp), "%02X%02X%02X", mac[3], mac[4], mac[5]); + g_userID = strdup(tmp); + // SERIAL - as in Tas, full 12 chars of MAC, so 5c cf 7f 13 9f 3d + snprintf(tmp, sizeof(tmp), "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + g_serial = strdup(tmp); + // BridgeID - as in Tas, full 12 chars of MAC with FFFE inside, so 5C CF 7F FFFE 13 9F 3D + snprintf(tmp, sizeof(tmp), "%02X%02X%02XFFFE%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + g_bridgeID = strdup(tmp); + // uuid + snprintf(tmp, sizeof(tmp), "f6543a06-da50-11ba-8d8f-%s", g_serial); + g_uid = strdup(tmp); + + + //HTTP_RegisterCallback("/api", HTTP_ANY, HUE_APICall); + HTTP_RegisterCallback("/description.xml", HTTP_GET, HUE_Setup); +} + diff --git a/src/driver/drv_kp18058.c b/src/driver/drv_kp18058.c new file mode 100644 index 000000000..a4c9e894c --- /dev/null +++ b/src/driver/drv_kp18058.c @@ -0,0 +1,110 @@ +#include "../new_common.h" +#include "../new_pins.h" +#include "../new_cfg.h" +// Commands register, execution API and cmd tokenizer +#include "../cmnds/cmd_public.h" +#include "../mqtt/new_mqtt.h" +#include "../logging/logging.h" +#include "drv_local.h" +#include "drv_uart.h" +#include "../httpserver/new_http.h" +#include "../hal/hal_pins.h" + + +static softI2C_t g_softI2C; + +byte CountBytes(byte b) { + byte sum; + int i; + + sum = 0; + for (i = 1; i < 8; i++) { + if (BIT_CHECK(b, i)) { + sum++; + } + } + if (sum % 2 == 0) { + return 0; + } + return 1; +} + +void KP18058_Write(float *rgbcw) { + bool bAllZero = true; + int i; + + + for (int i = 0; i < 5; i++) { + if (rgbcw[i] > 0.01f) { + bAllZero = false; + } + } + + if (bAllZero) { + Soft_I2C_Start(&g_softI2C, 0x81); + Soft_I2C_WriteByte(&g_softI2C, 0x00); + Soft_I2C_WriteByte(&g_softI2C, 0x03); + Soft_I2C_WriteByte(&g_softI2C, 0x7D); + for (int i = 0; i < 10; i++) { + Soft_I2C_WriteByte(&g_softI2C, 0x00); + } + } + else { + //FILE *f = fopen("dimmerTest.txt", "a"); + Soft_I2C_Start(&g_softI2C, 0xE1); + Soft_I2C_WriteByte(&g_softI2C, 0x00); + Soft_I2C_WriteByte(&g_softI2C, 0x03); + Soft_I2C_WriteByte(&g_softI2C, 0x7D); + for (int i = 0; i < 5; i++) { + float useVal = rgbcw[g_cfg.ledRemap.ar[i]]; + unsigned short cur_col_12 = MAP(useVal, 0, 255.0f, 0, 1023.0f); + byte a, b; + a = cur_col_12 & 0x1F; + b = (cur_col_12 >> 5) & 0x1F; + a = a << 1; + b = b << 1; + a |= CountBytes(a); + b |= CountBytes(b); + Soft_I2C_WriteByte(&g_softI2C, b); + Soft_I2C_WriteByte(&g_softI2C, a); + + //fprintf(f, "0x%02X 0x%02X ", b, a); + } + //fprintf(f, "\n"); + //fclose(f); + } + Soft_I2C_Stop(&g_softI2C); +} + +// startDriver KP18058 +// KP18058_Map 0 1 2 3 4 +// KP18058_RGBCW FF00000000 +void KP18058_Init() { + // default map + CFG_SetDefaultLEDRemap(2, 0, 1, 3, 4); + + g_softI2C.pin_clk = 7; + g_softI2C.pin_data = 8; + g_softI2C.pin_clk = PIN_FindPinIndexForRole(IOR_KP18058_CLK, g_softI2C.pin_clk); + g_softI2C.pin_data = PIN_FindPinIndexForRole(IOR_KP18058_DAT, g_softI2C.pin_data); + + Soft_I2C_PreInit(&g_softI2C); +#if 0 + for (float f = 0; f < 255; f += 0.25f) { + float rgbcw[5] = { 0 }; + rgbcw[1] = f; + KP18058_Write(rgbcw); + } +#endif + + //cmddetail:{"name":"KP18058_RGBCW","args":"[HexColor]", + //cmddetail:"descr":"Don't use it. It's for direct access of KP18058 driver. You don't need it because LED driver automatically calls it, so just use led_basecolor_rgb", + //cmddetail:"fn":"KP18058_RGBCW","file":"driver/drv_bp5758d.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("KP18058_RGBCW", CMD_LEDDriver_WriteRGBCW, NULL); + //cmddetail:{"name":"KP18058_Map","args":"[Ch0][Ch1][Ch2][Ch3][Ch4]", + //cmddetail:"descr":"Maps KP18058_Map RGBCW values to given indices of KP18058 channels. This is because KP18058 channels order is not the same for some devices. Some devices are using RGBCW order and some are using GBRCW, etc, etc. Example usage: KP18058_Map 0 1 2 3 4", + //cmddetail:"fn":"KP18058_Map","file":"driver/drv_sm2235.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("KP18058_Map", CMD_LEDDriver_Map, NULL); +} diff --git a/src/driver/drv_kp18068.c b/src/driver/drv_kp18068.c index 79eadab06..455c184bc 100644 --- a/src/driver/drv_kp18068.c +++ b/src/driver/drv_kp18068.c @@ -41,8 +41,8 @@ void KP18068_Write(float *rgbcw) { // KP18068_RGBCW FF00000000 void KP18068_Init() { - g_softI2C.pin_clk = 1111; - g_softI2C.pin_data = 111111111; + g_softI2C.pin_clk = 26; + g_softI2C.pin_data = 24; //g_softI2C.pin_clk = PIN_FindPinIndexForRole(IOR_KP18068_CLK, g_softI2C.pin_clk); //g_softI2C.pin_data = PIN_FindPinIndexForRole(IOR_KP18068_DAT, g_softI2C.pin_data); diff --git a/src/driver/drv_local.h b/src/driver/drv_local.h index ff5d1e8d7..84766115b 100644 --- a/src/driver/drv_local.h +++ b/src/driver/drv_local.h @@ -37,6 +37,8 @@ void BP5758D_Init(); void BP1658CJ_Init(); void KP18068_Init(); +void KP18058_Init(); + void SM16703P_Init(); @@ -46,6 +48,8 @@ void GN6932_Init(); void TM1638_Init(); +void HT16K33_Init(); + bool DRV_IsRunning(const char* name); // this is exposed here only for debug tool with automatic testing @@ -96,6 +100,18 @@ void DRV_MAX72XX_Init(); void WEMO_Init(); void WEMO_AppendInformationToHTTPIndexPage(http_request_t* request); +void HUE_Init(); +void HUE_AppendInformationToHTTPIndexPage(http_request_t* request); + +void MCP9808_Init(); +void MCP9808_OnEverySecond(); +void MCP9808_AppendInformationToHTTPIndexPage(http_request_t* request); + +void ChargingLimit_Init(); +void ChargingLimit_OnEverySecond(); +void ChargingLimit_AppendInformationToHTTPIndexPage(http_request_t *request); + + #define SM2135_DELAY 4 // Software I2C diff --git a/src/driver/drv_main.c b/src/driver/drv_main.c index a17f6cfc6..14843235d 100644 --- a/src/driver/drv_main.c +++ b/src/driver/drv_main.c @@ -123,6 +123,13 @@ static driver_t g_drivers[] = { //drvdetail:"requires":""} { "BL0942SPI", BL0942_SPI_Init, BL0942_SPI_RunFrame, BL09XX_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, #endif +#ifdef ENABLE_DRIVER_CHARGINGLIMIT + //drvdetail:{"name":"ChargingLimit", + //drvdetail:"title":"TODO", + //drvdetail:"descr":"ChargingLimit", + //drvdetail:"requires":""} + { "ChargingLimit", ChargingLimit_Init, ChargingLimit_OnEverySecond, ChargingLimit_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, +#endif #ifdef ENABLE_DRIVER_BL0937 //drvdetail:{"name":"BL0937", //drvdetail:"title":"TODO", @@ -138,11 +145,13 @@ static driver_t g_drivers[] = { { "CSE7766", CSE7766_Init, CSE7766_RunFrame, BL09XX_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, #endif #if PLATFORM_BEKEN +#if PLATFORM_BK7231N //drvdetail:{"name":"SM16703P", //drvdetail:"title":"TODO", //drvdetail:"descr":"WIP driver", //drvdetail:"requires":""} { "SM16703P", SM16703P_Init, NULL, NULL, NULL, NULL, NULL, false }, +#endif //drvdetail:{"name":"IR", //drvdetail:"title":"TODO", //drvdetail:"descr":"IRLibrary wrapper, so you can receive remote signals and send them. See [forum discussion here](https://www.elektroda.com/rtvforum/topic3920360.html), also see [LED strip and IR YT video](https://www.youtube.com/watch?v=KU0tDwtjfjw)", @@ -160,17 +169,26 @@ static driver_t g_drivers[] = { //drvdetail:"descr":"SSDP is a discovery protocol, so BK devices can show up in, for example, Windows network section", //drvdetail:"requires":""} { "SSDP", DRV_SSDP_Init, DRV_SSDP_RunEverySecond, NULL, DRV_SSDP_RunQuickTick, DRV_SSDP_Shutdown, NULL, false }, - //drvdetail:{"name":"Wemo", - //drvdetail:"title":"TODO", - //drvdetail:"descr":"Wemo emulation for Alexa. You must also start SSDP so it can run, because it depends on SSDP discovery.", - //drvdetail:"requires":""} - { "Wemo", WEMO_Init, NULL, WEMO_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, //drvdetail:{"name":"DGR", //drvdetail:"title":"TODO", //drvdetail:"descr":"Tasmota Device groups driver. See [forum example](https://www.elektroda.com/rtvforum/topic3925472.html) and TODO-video tutorial (will post on YT soon)", //drvdetail:"requires":""} { "DGR", DRV_DGR_Init, DRV_DGR_RunEverySecond, DRV_DGR_AppendInformationToHTTPIndexPage, DRV_DGR_RunQuickTick, DRV_DGR_Shutdown, DRV_DGR_OnChannelChanged, false }, #endif +#if ENABLE_DRIVER_WEMO + //drvdetail:{"name":"Wemo", + //drvdetail:"title":"TODO", + //drvdetail:"descr":"Wemo emulation for Alexa. You must also start SSDP so it can run, because it depends on SSDP discovery.", + //drvdetail:"requires":""} + { "Wemo", WEMO_Init, NULL, WEMO_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, +#endif +#if ENABLE_DRIVER_HUE + //drvdetail:{"name":"Hue", + //drvdetail:"title":"TODO", + //drvdetail:"descr":"Hue emulation for Alexa. You must also start SSDP so it can run, because it depends on SSDP discovery.", + //drvdetail:"requires":""} + { "Hue", HUE_Init, NULL, HUE_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, +#endif #if defined(PLATFORM_BEKEN) || defined(WINDOWS) //drvdetail:{"name":"PWMToggler", //drvdetail:"title":"TODO", @@ -182,11 +200,14 @@ static driver_t g_drivers[] = { //drvdetail:"descr":"DoorSensor is using deep sleep to preserve battery. This is used for devices without TuyaMCU, where BK deep sleep and wakeup on GPIO is used. This drives requires you to set a DoorSensor pin. Change on door sensor pin wakes up the device. If there are no changes for some time, device goes to sleep. See example [here](https://www.elektroda.com/rtvforum/topic3960149.html). If your door sensor does not wake up in certain pos, please use DSEdge command (try all 3 options, default is 2). ", //drvdetail:"requires":""} { "DoorSensor", DoorDeepSleep_Init, DoorDeepSleep_OnEverySecond, DoorDeepSleep_AppendInformationToHTTPIndexPage, NULL, NULL, DoorDeepSleep_OnChannelChanged, false }, + +#ifdef ENABLE_DRIVER_MAX72XX //drvdetail:{"name":"MAX72XX_Clock", //drvdetail:"title":"TODO", //drvdetail:"descr":"Simple hardcoded driver for MAX72XX clock. Requirex manual start of MAX72XX driver with MAX72XX setup and NTP start.", //drvdetail:"requires":""} { "MAX72XX_Clock", DRV_MAX72XX_Clock_Init, DRV_MAX72XX_Clock_OnEverySecond, NULL, DRV_MAX72XX_Clock_RunFrame, NULL, NULL, false }, +#endif //drvdetail:{"name":"ADCButton", //drvdetail:"title":"TODO", //drvdetail:"descr":"This allows you to connect multiple buttons on single ADC pin. Each button must have a different resistor value, this works by probing the voltage on ADC from a resistor divider. You need to select AB_Map first. See forum post for [details](https://www.elektroda.com/rtvforum/viewtopic.php?p=20541973#20541973).", @@ -221,16 +242,28 @@ static driver_t g_drivers[] = { //drvdetail:"descr":"CHT8305 is a Temperature and Humidity sensor with I2C interface.", //drvdetail:"requires":""} { "CHT8305", CHT8305_Init, CHT8305_OnEverySecond, CHT8305_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, + //drvdetail:{"name":"MCP9808", + //drvdetail:"title":"TODO", + //drvdetail:"descr":"MCP9808 is a Temperature sensor with I2C interface and an external wakeup pin, see [docs](https://www.elektroda.pl/rtvforum/topic3988466.html).", + //drvdetail:"requires":""} + { "MCP9808", MCP9808_Init, MCP9808_OnEverySecond, MCP9808_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, //drvdetail:{"name":"KP18068", //drvdetail:"title":"TODO", - //drvdetail:"descr":"KP18068 I2C LED driver", + //drvdetail:"descr":"KP18068 I2C LED driver. Unfinished due to the lack of the information.", //drvdetail:"requires":""} { "KP18068", KP18068_Init, NULL, NULL, NULL, NULL, NULL, false }, + //drvdetail:{"name":"KP18058", + //drvdetail:"title":"TODO", + //drvdetail:"descr":"KP18058 I2C LED driver. Working, see reverse-engineering [topic](https://www.elektroda.pl/rtvforum/topic3991620.html)", + //drvdetail:"requires":""} + { "KP18058", KP18058_Init, NULL, NULL, NULL, NULL, NULL, false }, +#ifdef ENABLE_DRIVER_MAX72XX //drvdetail:{"name":"MAX72XX", //drvdetail:"title":"TODO", - //drvdetail:"descr":"MAX72XX LED matrix display driver with font and simple script interface.", + //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, false }, +#endif //drvdetail:{"name":"TM1637", //drvdetail:"title":"TODO", //drvdetail:"descr":"Driver for 7-segment LED display with DIO/CLK interface", @@ -246,6 +279,13 @@ static driver_t g_drivers[] = { //drvdetail:"descr":"Driver for 7-segment LED display with DIO/CLK/STB interface. TM1638 is very similiar to GN6932 and TM1637. See [this topic](https://www.elektroda.com/rtvforum/viewtopic.php?p=20553628#20553628) for details.", //drvdetail:"requires":""} { "TM1638", TM1638_Init, NULL, NULL, TMGN_RunQuickTick,NULL, NULL, false }, +#if ENABLE_DRIVER_HT16K33 + //drvdetail:{"name":"HT16K33", + //drvdetail:"title":"TODO", + //drvdetail:"descr":"Driver for 16-segment LED display with I2C. See [protocol explanation](https://www.elektroda.pl/rtvforum/topic3984616.html)", + //drvdetail:"requires":""} + { "HT16K33", HT16K33_Init, NULL, NULL, NULL,NULL, NULL, false }, +#endif //drvdetail:{"name":"SHT3X", //drvdetail:"title":"TODO", //drvdetail:"descr":"Humidity/temperature sensor. See [SHT Sensor tutorial topic here](https://www.elektroda.com/rtvforum/topic3958369.html), also see [this sensor teardown](https://www.elektroda.com/rtvforum/topic3945688.html)", diff --git a/src/driver/drv_mcp9808.c b/src/driver/drv_mcp9808.c new file mode 100644 index 000000000..29d596740 --- /dev/null +++ b/src/driver/drv_mcp9808.c @@ -0,0 +1,287 @@ +// based on MCP9808_RT by RobTillaart +#include "../new_common.h" +#include "../new_pins.h" +#include "../new_cfg.h" +// Commands register, execution API and cmd tokenizer +#include "../cmnds/cmd_public.h" +#include "../mqtt/new_mqtt.h" +#include "../logging/logging.h" +#include "drv_local.h" +#include "drv_uart.h" +#include "../httpserver/new_http.h" +#include "../hal/hal_pins.h" + +#define MCP9808_RFU 0x00 +#define MCP9808_CONFIG 0x01 +#define MCP9808_TUPPER 0x02 +#define MCP9808_TLOWER 0x03 +#define MCP9808_TCRIT 0x04 +#define MCP9808_TA 0x05 +#define MCP9808_MID 0x06 +#define MCP9808_DID 0x07 +#define MCP9808_RES 0x08 + +static int g_targetChannel = -1; +static softI2C_t g_softI2C; +static byte g_addr = 30; +static float g_temp = 0.0f; +static int g_mcp_secondsBetweenMeasurements = 10; +static int g_mcp_secondsUntilNextMeasurement = 0; +static float g_mcp_userCalibrationDelta = 0.0f; + +void MCP9808_WriteReg16(uint8_t reg, uint16_t value) +{ + if (reg > MCP9808_RES) + return; // see p.16 + Soft_I2C_Start(&g_softI2C, g_addr); + Soft_I2C_WriteByte(&g_softI2C, reg); + Soft_I2C_WriteByte(&g_softI2C, value >> 8); + Soft_I2C_WriteByte(&g_softI2C, value & 0xFF); + Soft_I2C_Stop(&g_softI2C); +} +uint16_t MCP9808_ReadReg16(uint8_t reg) +{ + byte reply[2]; + + Soft_I2C_Start(&g_softI2C, g_addr); + Soft_I2C_WriteByte(&g_softI2C, reg); + Soft_I2C_Stop(&g_softI2C); + + rtos_delay_milliseconds(20); //give the sensor time to do the conversion + + Soft_I2C_Start(&g_softI2C, g_addr | 1); + Soft_I2C_ReadBytes(&g_softI2C, reply, 2); + Soft_I2C_Stop(&g_softI2C); + + uint16_t val = reply[0] << 8; + val += reply[1]; + return val; +} +float MCP9808_ReadFloat(uint8_t reg) +{ + uint16_t val = MCP9808_ReadReg16(reg); + if (val & 0x1000) // negative value + { + return ((val & 0x0FFF) * 0.0625) - 256.0; + } + return (val & 0x0FFF) * 0.0625; +} +void MCP9808_WriteFloat(uint8_t reg, float f) +{ + bool neg = (f < 0.0); + if (neg) + f = -f; + uint16_t val = ((uint16_t)(f * 4 + 0.5)) * 4; + if (neg) + val |= 0x1000; + MCP9808_WriteReg16(reg, val); +} + +void MCP9808_SetConfigRegister(uint16_t configuration) +{ + MCP9808_WriteReg16(MCP9808_CONFIG, configuration); +} + +uint16_t MCP9808_GetConfigRegister() +{ + return MCP9808_ReadReg16(MCP9808_CONFIG); +} + +void MCP9808_SetTupper(float temperature) +{ + MCP9808_WriteFloat(MCP9808_TUPPER, temperature); +} + +float MCP9808_GetTupper() +{ + return MCP9808_ReadFloat(MCP9808_TUPPER); +} + +void MCP9808_SetTlower(float temperature) +{ + MCP9808_WriteFloat(MCP9808_TLOWER, temperature); +} + + +float MCP9808_GetTlower() +{ + return MCP9808_ReadFloat(MCP9808_TLOWER); +} +void MCP9808_SetTcritical(float temperature) +{ + MCP9808_WriteFloat(MCP9808_TCRIT, temperature); +} + + +float MCP9808_GetTcritical() +{ + return MCP9808_ReadFloat(MCP9808_TCRIT); +} + +void MCP9808_Measure() { + g_temp = MCP9808_ReadFloat(MCP9808_TA) + g_mcp_userCalibrationDelta; + if (g_targetChannel >= 0) { + int type = CHANNEL_GetType(g_targetChannel); + if (type == ChType_Temperature_div10) { + CHANNEL_Set(g_targetChannel, g_temp * 10, 0); + } + else { + CHANNEL_Set(g_targetChannel, g_temp, 0); + } + } +} +commandResult_t MCP9808_Adr(const void* context, const char* cmd, const char* args, int cmdFlags) { + + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND); + if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + g_addr = Tokenizer_GetArgInteger(0); + + return CMD_RES_OK; +} +commandResult_t MCP9808_Calibrate(const void* context, const char* cmd, const char* args, int cmdFlags) { + + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND); + if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + g_mcp_userCalibrationDelta = Tokenizer_GetArgFloat(0); + + + return CMD_RES_OK; +} +commandResult_t MCP9808_cycle(const void* context, const char* cmd, const char* args, int cmdFlags) { + + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND); + if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + g_mcp_secondsBetweenMeasurements = Tokenizer_GetArgInteger(0); + + + return CMD_RES_OK; +} +// MCP9808_AlertRange [MinT] [MaxT] [OptionalBActiveHigh] +// MCP9808_AlertRange 20 26 1 +commandResult_t MCP9808_AlertRange(const void* context, const char* cmd, const char* args, int cmdFlags) { + float min, max; + int bActiveHigh; + + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND); + if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + min = Tokenizer_GetArgFloat(0); + max = Tokenizer_GetArgFloat(1); + bActiveHigh = Tokenizer_GetArgIntegerDefault(2, 0); + MCP9808_SetTlower(min); + MCP9808_SetTupper(max); + MCP9808_SetTcritical(max); + + // SET ALERT PARAMETERS + uint16_t cfg = MCP9808_GetConfigRegister(); + cfg &= ~0x0001; // set comparator mode + if (bActiveHigh) { + cfg &= ~0x0002; // set polarity HIGH + } + else { + cfg |= 0x0002; // set polarity LOW + } + cfg &= ~0x0004; // use upper lower and critical + cfg |= 0x0008; // enable alert + MCP9808_SetConfigRegister(cfg); + + return CMD_RES_OK; +} +// MCP9808_AlertMin [MinT] [OptionalBActiveHigh] +// MCP9808_AlertMin 20 1 +commandResult_t MCP9808_AlertMin(const void* context, const char* cmd, const char* args, int cmdFlags) { + float min; + int bActiveHigh; + + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND); + if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + min = Tokenizer_GetArgFloat(0); + bActiveHigh = Tokenizer_GetArgIntegerDefault(1, 0); + MCP9808_SetTcritical(min); + + // SET ALERT PARAMETERS + uint16_t cfg = MCP9808_GetConfigRegister(); + cfg &= ~0x0001; // set comparator mode + if (bActiveHigh) { + cfg &= ~0x0002; // set polarity HIGH + } + else { + cfg |= 0x0002; // set polarity LOW + } + // TA > TCRIT only + cfg |= 0x0004; // use only critical + cfg |= 0x0008; // enable alert + MCP9808_SetConfigRegister(cfg); + + return CMD_RES_OK; +} +// driver initialization +// startDriver MCP9808 [ClkPin] [DatPin] [OptionalTargetChannel] +// startDriver MCP9808 26 24 +// startDriver MCP9808 26 24 1 +// startDriver MCP9808 12 13 1 +void MCP9808_Init() { + + uint8_t buff[4]; + + g_softI2C.pin_clk = Tokenizer_GetArgIntegerDefault(1, 26); + g_softI2C.pin_data = Tokenizer_GetArgIntegerDefault(2, 24); + g_targetChannel = Tokenizer_GetArgIntegerDefault(3,-1); + + Soft_I2C_PreInit(&g_softI2C); + + //cmddetail:{"name":"MCP9808_Adr","args":"MCP9808_Adr", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_mcp9808.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("MCP9808_Adr", MCP9808_Adr, NULL); + + //cmddetail:{"name":"MCP9808_AlertRange","args":"MCP9808_AlertRange", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_mcp9808.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("MCP9808_AlertRange", MCP9808_AlertRange, NULL); + //cmddetail:{"name":"MCP9808_AlertMin","args":"MCP9808_AlertMin", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_mcp9808.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("MCP9808_AlertMin", MCP9808_AlertMin, NULL); + + + //cmddetail:{"name":"MCP9808_Calibrate","args":"MCP9808_Calibrate", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_mcp9808.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("MCP9808_Calibrate", MCP9808_Calibrate, NULL); + //cmddetail:{"name":"MCP9808_Cycle","args":"MCP9808_cycle", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_mcp9808.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("MCP9808_Cycle", MCP9808_cycle, NULL); + +} +void MCP9808_OnEverySecond() { + + if (g_mcp_secondsUntilNextMeasurement <= 0) { + MCP9808_Measure(); + g_mcp_secondsUntilNextMeasurement = g_mcp_secondsBetweenMeasurements; + } + if (g_mcp_secondsUntilNextMeasurement > 0) { + g_mcp_secondsUntilNextMeasurement--; + } +} + +void MCP9808_AppendInformationToHTTPIndexPage(http_request_t* request) +{ + hprintf255(request, "

MCP9808 Temperature=%f

", g_temp); +} + diff --git a/src/driver/drv_public.h b/src/driver/drv_public.h index 92313959d..c51d0d81b 100644 --- a/src/driver/drv_public.h +++ b/src/driver/drv_public.h @@ -47,6 +47,7 @@ void SM2135_Write(float* rgbcw); void BP5758D_Write(float* rgbcw); void BP1658CJ_Write(float* rgbcw); void SM2235_Write(float* rgbcw); +void KP18058_Write(float *rgbcw); void DRV_DGR_OnLedDimmerChange(int iVal); void DRV_DGR_OnLedEnableAllChange(int iVal); void DRV_DGR_OnLedFinalColorsChange(byte rgbcw[5]); @@ -58,5 +59,10 @@ bool DRV_IsMeasuringBattery(); bool DRV_IsSensor(); void BL09XX_SaveEmeteringStatistics(); +// TuyaMCU exports for LED +void TuyaMCU_OnRGBCWChange(const float *rgbcw, int bLightEnableAll, int iLightMode, float brightnessRange01, float temperatureRange01); +bool TuyaMCU_IsLEDRunning(); + + #endif /* __DRV_PUBLIC_H__ */ diff --git a/src/driver/drv_pwmToggler.c b/src/driver/drv_pwmToggler.c index 6a31cdb58..fc2ad77b0 100644 --- a/src/driver/drv_pwmToggler.c +++ b/src/driver/drv_pwmToggler.c @@ -59,7 +59,9 @@ addEventHandler LEDState 0 backlog toggler_enable0 0; toggler_enable1 0; // Comment out if you don't want it! addEventHandler LEDState 1 backlog toggler_enable0 1; toggler_enable1 1; - +To set startup value, use: +toggler_set0 50 +toggler_enable0 1 */ diff --git a/src/driver/drv_sm16703P.c b/src/driver/drv_sm16703P.c index efdd86ca7..4a99b07b0 100644 --- a/src/driver/drv_sm16703P.c +++ b/src/driver/drv_sm16703P.c @@ -1,235 +1,192 @@ -#if PLATFORM_BEKEN -#include "../new_common.h" -#include "../new_pins.h" -#include "../new_cfg.h" -// Commands register, execution API and cmd tokenizer -#include "../cmnds/cmd_public.h" -#include "../mqtt/new_mqtt.h" -#include "../logging/logging.h" -#include "../hal/hal_pins.h" -#include "../httpserver/new_http.h" +#if PLATFORM_BK7231N -// SM16703P is 3 channels each. -// We send 24 bits. 24 / 8 = 3. Send byte per each channel. - -static int g_pin_di = 0; - -/*1 equals about 5 us*/ -// From platforms/bk7231t/bk7231t_os/beken378/driver/codec/driver_codec_es8374.c -static void es8374_codec_i2c_delay1equalsabout5us(int us) -{ - volatile int i, j; - for (i = 0; i < us; i++) - { - j = 50; - while (j--); - } -} -/*1 equals about 0.3 us*/ -static void es8374_codec_i2c_delay(int us) -{ - volatile int i, j; - for (i = 0; i < us; i++) - { - j = 3; - while (j--); - } -} -#define SM16703P_SLEEP_300 __asm("nop\nnop\nnop"); -#define SM16703P_SLEEP_900 __asm("nop\nnop\nnop\nnop\nnop\nnop\nnop"); - -void gpio_output(UINT32 id, UINT32 val); - - -//#define SM16703P_SET_HIGH gpio_output(g_pin_di,true); -//#define SM16703P_SET_LOW gpio_output(g_pin_di,false); - -// NOTE: #define REG_WRITE(addr, _data) (*((volatile UINT32 *)(addr)) = (_data)) -#define SM16703P_SET_HIGH REG_WRITE(gpio_cfg_addr, reg_val_HIGH); -#define SM16703P_SET_LOW REG_WRITE(gpio_cfg_addr, reg_val_LOW); - -// gpio_output is faster -#define SM16703P_SEND_T0 SM16703P_SET_HIGH; SM16703P_SLEEP_300; SM16703P_SET_LOW; SM16703P_SLEEP_900; -#define SM16703P_SEND_T1 SM16703P_SET_HIGH; SM16703P_SLEEP_900; SM16703P_SET_LOW; SM16703P_SLEEP_300; - -#ifndef CHECK_BIT -#define CHECK_BIT(var,pos) ((var) & (1<<(pos))) -#endif - -#define SM16703P_SEND_BIT(var,pos) if(((var) & (1<<(pos)))) { SM16703P_SEND_T1; } else { SM16703P_SEND_T0; }; - - -#include "include.h" #include "arm_arch.h" -#include "gpio_pub.h" -#include "gpio.h" #include "drv_model_pub.h" +#include "gpio.h" +#include "gpio_pub.h" +#include "icu_pub.h" +#include "include.h" +#include "intc_pub.h" #include "sys_ctrl_pub.h" #include "uart_pub.h" -#include "intc_pub.h" -#include "icu_pub.h" -static void SM16703P_Send(byte *data, int dataSize){ - //int i; - //byte b; - UINT32 reg_val = 0; - volatile UINT32 *gpio_cfg_addr; - UINT32 id; - volatile UINT32 reg_val_HIGH = 0x02; - volatile UINT32 reg_val_LOW = 0x00; +#include "../new_cfg.h" +#include "../new_common.h" +#include "../new_pins.h" +// Commands register, execution API and cmd tokenizer +#include "../cmnds/cmd_public.h" +#include "../hal/hal_pins.h" +#include "../httpserver/new_http.h" +#include "../logging/logging.h" +#include "../mqtt/new_mqtt.h" +#include "drv_spidma.h" - GLOBAL_INT_DECLARATION(); - GLOBAL_INT_DISABLE(); +static uint8_t data_translate[4] = {0b10001000, 0b10001110, 0b11101000, 0b11101110}; - // let things settle down a bit - es8374_codec_i2c_delay1equalsabout5us(100); +UINT8 *send_buf; +struct spi_message *spi_msg; +BOOLEAN initialized = false; +uint32_t pixel_count = 0; - id = g_pin_di; - -#if (CFG_SOC_NAME != SOC_BK7231) - if (id >= GPIO32) - id += 16; -#endif // (CFG_SOC_NAME != SOC_BK7231) - gpio_cfg_addr = (volatile UINT32 *)(REG_GPIO_CFG_BASE_ADDR + id * 4); - - SM16703P_SET_LOW; - SM16703P_SET_LOW; - SM16703P_SET_LOW; - SM16703P_SET_LOW; - - SM16703P_SEND_T0; - SM16703P_SEND_T0; - SM16703P_SEND_T0; - SM16703P_SEND_T0; - SM16703P_SEND_T0; - SM16703P_SEND_T0; - SM16703P_SEND_T0; - SM16703P_SEND_T0; - -/* SM16703P_SLEEP_900; - SM16703P_SLEEP_900; - SM16703P_SLEEP_900; - SM16703P_SLEEP_900; - - for(i = 0; i < dataSize; i++) { - b = data[i]; - SM16703P_SEND_BIT(b,0); - SM16703P_SEND_BIT(b,1); - SM16703P_SEND_BIT(b,2); - SM16703P_SEND_BIT(b,3); - SM16703P_SEND_BIT(b,4); - SM16703P_SEND_BIT(b,5); - SM16703P_SEND_BIT(b,6); - SM16703P_SEND_BIT(b,7); - }*/ - GLOBAL_INT_RESTORE(); - // For P0, it says - // For P11, it says 0 - // For P12, it says 0 - addLogAdv(LOG_INFO, LOG_FEATURE_ENERGYMETER, "Reg val is %i", reg_val); +static uint8_t translate_2bit(uint8_t input) { + //ADDLOG_INFO(LOG_FEATURE_CMD, "Translate 0x%02x to 0x%02x", (input & 0b00000011), data_translate[(input & 0b00000011)]); + return data_translate[(input & 0b00000011)]; } -static commandResult_t SM16703P_Test(const void *context, const char *cmd, const char *args, int flags){ - byte test[3]; - int i; - for(i = 0; i < 3; i++){ - test[i] = rand(); +static void translate_byte(uint8_t input, uint8_t *dst) { + // return 0x00000000 | + // translate_2bit((input >> 6)) | + // translate_2bit((input >> 4)) | + // translate_2bit((input >> 2)) | + // translate_2bit(input); + *dst++ = translate_2bit((input >> 6)); + *dst++ = translate_2bit((input >> 4)); + *dst++ = translate_2bit((input >> 2)); + *dst++ = translate_2bit(input); +} + +static void SM16703P_setMultiplePixel(uint32_t pixel, UINT8 *data) { + + // Return if driver is not loaded + if (!initialized) + return; + + // Check max pixel + if (pixel > pixel_count) + pixel = pixel_count; + + // Iterate over pixel + uint8_t *dst = spi_msg->send_buf + 2; + for (uint32_t i = 0; i < pixel * 3; i++) { + uint8_t input = *data++; + *dst++ = translate_2bit((input >> 6)); + *dst++ = translate_2bit((input >> 4)); + *dst++ = translate_2bit((input >> 2)); + *dst++ = translate_2bit(input); } - SM16703P_Send(test,3); +} + +commandResult_t SM16703P_CMD_setPixel(const void *context, const char *cmd, const char *args, int flags) { + int pixel, r, g, b; + Tokenizer_TokenizeString(args, 0); + + if (Tokenizer_GetArgsCount() != 4) { + ADDLOG_INFO(LOG_FEATURE_CMD, "Not Enough Arguments for init SM16703P: Amount of LEDs missing"); + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + + pixel = Tokenizer_GetArgIntegerRange(0, 0, 255); + r = Tokenizer_GetArgIntegerRange(1, 0, 255); + g = Tokenizer_GetArgIntegerRange(2, 0, 255); + b = Tokenizer_GetArgIntegerRange(3, 0, 255); + + ADDLOG_INFO(LOG_FEATURE_CMD, "Set Pixel %i to R %i G %i B %i", pixel, r, g, b); + + translate_byte(r, spi_msg->send_buf + (2 + 0 + (pixel * 3 * 4))); + translate_byte(g, spi_msg->send_buf + (2 + 4 + (pixel * 3 * 4))); + translate_byte(b, spi_msg->send_buf + (2 + 8 + (pixel * 3 * 4))); + + ADDLOG_INFO(LOG_FEATURE_CMD, "Raw Data 0x%02x 0x%02x 0x%02x 0x%02x - 0x%02x 0x%02x 0x%02x 0x%02x - 0x%02x 0x%02x 0x%02x 0x%02x", + spi_msg->send_buf[2 + 0 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 1 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 2 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 3 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 4 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 5 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 6 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 7 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 8 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 9 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 10 + (pixel * 3 * 4)], + spi_msg->send_buf[2 + 11 + (pixel * 3 * 4)]); return CMD_RES_OK; } -// backlog startDriver SM16703P; SM16703P_Test_3xZero -static commandResult_t SM16703P_Test_3xZero(const void *context, const char *cmd, const char *args, int flags) { - byte test[3]; +static void SM16703P_Send(byte *data, int dataSize) { + // ToDo +} + +commandResult_t SM16703P_Start(const void *context, const char *cmd, const char *args, int flags) { + + Tokenizer_TokenizeString(args, 0); + + if (Tokenizer_GetArgsCount() == 0) { + ADDLOG_INFO(LOG_FEATURE_CMD, "Not Enough Arguments for init SM16703P: Amount of LEDs missing"); + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + + pixel_count = Tokenizer_GetArgIntegerRange(0, 0, 255); + + ADDLOG_INFO(LOG_FEATURE_CMD, "Register driver with %i LEDs", pixel_count); + + // Prepare buffer + uint32_t buffer_size = 2 + (pixel_count * 3 * 4); //Add two bytes for "Reset" + send_buf = (UINT8 *)os_malloc(sizeof(UINT8) * (buffer_size)); //18LEDs x RGB x 4Bytes int i; - for (i = 0; i < 3; i++) { - test[i] = 0; - } - SM16703P_Send(test, 3); + send_buf[0] = 0; + send_buf[1] = 0; + for (i = 2; i < buffer_size; i++) { + send_buf[i] = 0b11101110; + } + + spi_msg = os_malloc(sizeof(struct spi_message)); + spi_msg->send_buf = send_buf; + spi_msg->send_len = buffer_size; + + SPIDMA_Init(spi_msg); + + initialized = true; return CMD_RES_OK; } -// backlog startDriver SM16703P; SM16703P_Test_3xOne -static commandResult_t SM16703P_Test_3xOne(const void *context, const char *cmd, const char *args, int flags) { - byte test[3]; - int i; - - for (i = 0; i < 3; i++) { - test[i] = 0xFF; - } - SM16703P_Send(test, 3); +static commandResult_t SM16703P_StartTX(const void *context, const char *cmd, const char *args, int flags) { + if (!initialized) + return CMD_RES_ERROR; + SPIDMA_StartTX(spi_msg); return CMD_RES_OK; } -static commandResult_t SM16703P_Send_Cmd(const void *context, const char *cmd, const char *args, int flags) { - byte test[32]; - int i; - const char *c; - int numBytes; - numBytes = 0; - c = args; - - for (i = 0; i < sizeof(test) && *c; i++) { - char tmp[3]; - int val; - int r; - tmp[0] = *c; - c++; - if (!*c) - break; - tmp[1] = *c; - c++; - tmp[2] = 0; - r = sscanf(tmp, "%x", &val); - if (!r) { - ADDLOG_ERROR(LOG_FEATURE_CMD, "SM16703P_Send_Cmd no sscanf hex result from %s", tmp); - break; - } - test[i] = val; - numBytes++; - } - ADDLOG_ERROR(LOG_FEATURE_CMD, "Will send %i bytes", numBytes); - SM16703P_Send(test, numBytes); - - - return CMD_RES_OK; -} // startDriver SM16703P // backlog startDriver SM16703P; SM16703P_Test void SM16703P_Init() { + initialized = false; - g_pin_di = PIN_FindPinIndexForRole(IOR_SM16703P_DIN,g_pin_di); + uint32_t val; - HAL_PIN_Setup_Output(g_pin_di); + val = GFUNC_MODE_SPI_USE_GPIO_14; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); - //cmddetail:{"name":"SM16703P_Test","args":"", - //cmddetail:"descr":"qq", - //cmddetail:"fn":"SM16703P_Test","file":"driver/drv_ucs1912.c","requires":"", + val = GFUNC_MODE_SPI_USE_GPIO_16_17; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); + + UINT32 param; + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + + param = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + + //cmddetail:{"name":"SM16703P_Init","args":"SM16703P_Start", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_sm16703P.c","requires":"", //cmddetail:"examples":""} - CMD_RegisterCommand("SM16703P_Test", SM16703P_Test, NULL); - //cmddetail:{"name":"SM16703P_Send","args":"", - //cmddetail:"descr":"NULL", - //cmddetail:"fn":"SM16703P_Send_Cmd","file":"driver/drv_sm16703P.c","requires":"", + CMD_RegisterCommand("SM16703P_Init", SM16703P_Start, NULL); + //cmddetail:{"name":"SM16703P_Start","args":"SM16703P_StartTX", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_sm16703P.c","requires":"", //cmddetail:"examples":""} - CMD_RegisterCommand("SM16703P_Send", SM16703P_Send_Cmd, NULL); - //cmddetail:{"name":"SM16703P_Test_3xZero","args":"", - //cmddetail:"descr":"NULL", - //cmddetail:"fn":"SM16703P_Test_3xZero","file":"driver/drv_sm16703P.c","requires":"", + CMD_RegisterCommand("SM16703P_Start", SM16703P_StartTX, NULL); + //cmddetail:{"name":"SM16703P_SetPixel","args":"SM16703P_CMD_setPixel", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_sm16703P.c","requires":"", //cmddetail:"examples":""} - CMD_RegisterCommand("SM16703P_Test_3xZero", SM16703P_Test_3xZero, NULL); - //cmddetail:{"name":"SM16703P_Test_3xOne","args":"", - //cmddetail:"descr":"NULL", - //cmddetail:"fn":"SM16703P_Test_3xOne","file":"driver/drv_sm16703P.c","requires":"", - //cmddetail:"examples":""} - CMD_RegisterCommand("SM16703P_Test_3xOne", SM16703P_Test_3xOne, NULL); + CMD_RegisterCommand("SM16703P_SetPixel", SM16703P_CMD_setPixel, NULL); } #endif - diff --git a/src/driver/drv_spidma.c b/src/driver/drv_spidma.c new file mode 100644 index 000000000..d026f83e2 --- /dev/null +++ b/src/driver/drv_spidma.c @@ -0,0 +1,516 @@ +#if PLATFORM_BK7231N +#include "arm_arch.h" + +#include "drv_model_pub.h" +#include "general_dma_pub.h" +#include "gpio_pub.h" +#include "icu_pub.h" +#include "spi_pub.h" + +#include "../../beken378/driver/general_dma/general_dma.h" +#include "../../beken378/driver/spi/spi.h" + +#include "../new_cfg.h" +#include "../new_common.h" +#include "../new_pins.h" + +// Commands register, execution API and cmd tokenizer +#include "../cmnds/cmd_public.h" +#include "../hal/hal_pins.h" +#include "../httpserver/new_http.h" +#include "../logging/logging.h" +#include "../mqtt/new_mqtt.h" + +#include "drv_spidma.h" + +static struct bk_spi_dev *spi_dev; + +static void setSpiCtrlRegister(unsigned long bit, BOOLEAN val) { + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) { + value &= ~bit; + } else if (val == 1) { + value |= bit; + } + REG_WRITE(SPI_CTRL, value); +} + +static void setSpiConfigRegister(unsigned long bit, BOOLEAN val) { + UINT32 value; + + value = REG_READ(SPI_CONFIG); + if (val == 0) { + value &= ~bit; + } else if (val == 1) { + value |= bit; + } + REG_WRITE(SPI_CONFIG, value); +} + +static void set_txtrans_len(UINT32 val) { + UINT32 value; + + value = REG_READ(SPI_CONFIG); + + value &= ~(0xFFF << SPI_TX_TRAHS_LEN_POSI); + value |= ((val & 0xFFF) << SPI_TX_TRAHS_LEN_POSI); + + REG_WRITE(SPI_CONFIG, value); +} + +void spidma_dma_tx_enable(UINT8 enable) { + int param; + GDMA_CFG_ST en_cfg; + + //enable tx + param = enable; + setSpiConfigRegister(SPI_TX_EN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_TX_EN, (void *)¶m); + en_cfg.channel = SPI_TX_DMA_CHANNEL; + + if (enable) + en_cfg.param = 1; + else + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + + +static void spi_set_nssmd(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + value &= ~CTRL_NSSMD_3; + value |= (val << 17); + REG_WRITE(SPI_CTRL, value); + +} + +static void spi_set_clock(UINT32 max_hz) +{ + int source_clk = 0; + int spi_clk = 0; + int div = 0; + UINT32 param; + //os_printf("\rmax_hz :%d\r\n", max_hz); + + if ((max_hz == 26000000) || (max_hz == 13000000) || (max_hz == 6500000)) { + BK_SPI_PRT("config spi clk source 26MHz\n"); + + spi_clk = max_hz; + +#if CFG_XTAL_FREQUENCE + + source_clk = CFG_XTAL_FREQUENCE; +#else + source_clk = SPI_PERI_CLK_26M; +#endif + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + } else if (max_hz > 4333000) { + BK_SPI_PRT("config spi clk source DCO\n"); + + if (max_hz > 30000000) { // 120M/2 / (2 + 1) = 30M + spi_clk = 30000000; + BK_SPI_PRT("input clk > 30MHz, set input clk = 30MHz\n"); + } else + spi_clk = max_hz; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); + source_clk = SPI_PERI_CLK_DCO; + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_DCO, ¶m); + param = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + } else { + BK_SPI_PRT("config spi clk source 26MHz\n"); + + spi_clk = max_hz; +#if CFG_XTAL_FREQUENCE + source_clk = CFG_XTAL_FREQUENCE; +#else + source_clk = SPI_PERI_CLK_26M; +#endif + + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + } + if ((max_hz == 26000000) || (max_hz == 13000000) || (max_hz == 6500000)) + div = source_clk / spi_clk - 1; + else { + // spi_clk = in_clk / (2 * (div + 1)) + div = ((source_clk >> 1) / spi_clk); + + if (div < 2) + div = 2; + else if (div >= 255) + div = 255; + } + + param = REG_READ(SPI_CTRL); + param &= ~(SPI_CKR_MASK << SPI_CKR_POSI); + param |= (div << SPI_CKR_POSI); + REG_WRITE(SPI_CTRL, param); + + BK_SPI_PRT("\rdiv = %d \r\n", div); + BK_SPI_PRT("\rspi_clk = %d \r\n", spi_clk); + BK_SPI_PRT("\rsource_clk = %d \r\n", source_clk); + BK_SPI_PRT("\rtarget frequency = %d, actual frequency = %d \r\n", max_hz, source_clk / 2 / div); +} + +static void spidma_spi_configure(UINT32 rate, UINT32 mode) { + UINT32 param; + //struct spi_callback_des spi_dev_cb; + + param = 0; + setSpiCtrlRegister(MSTEN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_INIT_MSTEN, (void *)¶m); + + /* data bit width */ + param = 0; + setSpiCtrlRegister(BIT_WDTH, param); //ToDo: check + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_BITWIDTH, (void *)¶m); + + /* baudrate */ + ADDLOG_DEBUG(LOG_FEATURE_CMD, "max_hz = %d \n", rate); + //setSpiCtrlRegister(BIT_WDTH, param); + spi_set_clock(rate); + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKR, (void *)&rate); + + /* mode */ + if (mode & BK_SPI_CPOL) + param = 1; + else + param = 0; + setSpiCtrlRegister(CKPOL, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKPOL, (void *)¶m); + + /* CPHA */ + if (mode & BK_SPI_CPHA) + param = 1; + else + param = 0; + setSpiCtrlRegister(CKPHA, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKPHA, (void *)¶m); + + /* Master */ + param = 1; + setSpiCtrlRegister(MSTEN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_MSTEN, (void *)¶m); + param = 1; + //setSpiCtrlRegister(MSTEN, param); + spi_set_nssmd(param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + + /* set call back func */ + // spi_dev_cb.callback = bk_spi_rx_callback; + // spi_dev_cb.param = NULL; + // sddev_control(SPI_DEV_NAME, CMD_SPI_SET_RX_CALLBACK, (void *)&spi_dev_cb); + // + // spi_dev_cb.callback = bk_spi_tx_needwrite_callback; + // spi_dev_cb.param = NULL; + // sddev_control(SPI_DEV_NAME, CMD_SPI_SET_TX_NEED_WRITE_CALLBACK, (void *)&spi_dev_cb); + // + // spi_dev_cb.callback = bk_spi_tx_finish_callback; + // spi_dev_cb.param = NULL; + // sddev_control(SPI_DEV_NAME, CMD_SPI_SET_TX_FINISH_CALLBACK, (void *)&spi_dev_cb); + + /* enable spi */ + param = 1; + setSpiCtrlRegister(SPIEN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_UNIT_ENABLE, (void *)¶m); + + + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi_master:[CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); +} + +static void spidma_spi_unconfigure(void) { + sddev_control(SPI_DEV_NAME, CMD_SPI_DEINIT_MSTEN, NULL); +} + +int spidma_spi_master_deinit(void) { + if (spi_dev == NULL) + return 0; + + if (spi_dev->mutex) + rtos_lock_mutex(&spi_dev->mutex); + + if (spi_dev->tx_sem) + rtos_deinit_semaphore(&spi_dev->tx_sem); + if (spi_dev->rx_sem) + rtos_deinit_semaphore(&spi_dev->rx_sem); + if (spi_dev->dma_tx_sem) + rtos_deinit_semaphore(&spi_dev->dma_tx_sem); + if (spi_dev->dma_rx_sem) + rtos_deinit_semaphore(&spi_dev->dma_rx_sem); + + if (spi_dev->mutex) { + rtos_unlock_mutex(&spi_dev->mutex); + rtos_deinit_mutex(&spi_dev->mutex); + } + + if (spi_dev) { + os_free(spi_dev); + spi_dev = NULL; + } + + spidma_spi_unconfigure(); + + return 0; +} + +void spidma_spi_dma_tx_finish_callback(UINT32 param) { + + spi_dev->flag &= ~(TX_FINISH_FLAG); + rtos_set_semaphore(&spi_dev->dma_tx_sem); + + //ToDo: USer + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi dma tx finish callback\r\n"); + spidma_dma_tx_enable(0); +} + + +int spidma_dma_master_tx_init(struct spi_message *spi_msg) { + GDMACFG_TPYES_ST init_cfg; + GDMA_CFG_ST en_cfg; + + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi dma tx init\r\n"); + os_memset(&init_cfg, 0, sizeof(GDMACFG_TPYES_ST)); + os_memset(&en_cfg, 0, sizeof(GDMA_CFG_ST)); + + init_cfg.dstdat_width = 8; + init_cfg.srcdat_width = 32; + init_cfg.dstptr_incr = 0; + init_cfg.srcptr_incr = 1; + + init_cfg.src_start_addr = spi_msg->send_buf; + init_cfg.dst_start_addr = (void *)SPI_DAT; + + init_cfg.channel = SPI_TX_DMA_CHANNEL; + init_cfg.prio = 10; + init_cfg.u.type4.src_loop_start_addr = spi_msg->send_buf; + init_cfg.u.type4.src_loop_end_addr = spi_msg->send_buf + spi_msg->send_len; + + init_cfg.half_fin_handler = NULL; + init_cfg.fin_handler = spidma_spi_dma_tx_finish_callback; + //spi_ctrl(CMD_SPI_SET_TX_FINISH_INT_CALLBACK, (void *)spidma_spi_dma_tx_finish_callback); + + init_cfg.src_module = GDMA_X_SRC_DTCM_RD_REQ; + init_cfg.dst_module = GDMA_X_DST_GSPI_TX_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE4, (void *)&init_cfg); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = spi_msg->send_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi dma tx config: length:%d, first:%d\r\n", spi_msg->send_len, spi_msg->send_buf[0]); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; // 0:not repeat 1:repeat + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_WORK_MODE, (void *)&en_cfg); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; // src no loop + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_SRCADDR_LOOP, &en_cfg); + + return 0; +} + +void spidma_spi_master_dma_config(UINT32 mode, UINT32 rate) { + UINT32 param; + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi master dma init: mode:%d, rate:%d\r\n", mode, rate); + spidma_spi_configure(rate, mode); + + //disable tx/rx int disable + param = 0; + setSpiCtrlRegister(TXINT_EN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + param = 0; + setSpiCtrlRegister(RXINT_EN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_RXINT_EN, (void *)¶m); + + //disable rx/tx finish enable bit + param = 1; + setSpiConfigRegister(SPI_TX_FINISH_EN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_TXFINISH_EN, (void *)¶m); + + param = 1; + setSpiConfigRegister(SPI_RX_FINISH_EN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_RXFINISH_EN, (void *)¶m); + + //disable rx/tx over + param = 0; + setSpiCtrlRegister(RXOVR_EN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_RXOVR_EN, (void *)¶m); + + param = 0; + setSpiCtrlRegister(TXOVR_EN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_TXOVR_EN, (void *)¶m); + + param = 1; + spi_set_nssmd(param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_3_LINE, NULL); + uint32_t val; + + val = GFUNC_MODE_SPI_USE_GPIO_14; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); + + val = GFUNC_MODE_SPI_USE_GPIO_16_17; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); + + + param = 0; + setSpiCtrlRegister(BIT_WDTH, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_BITWIDTH, (void *)¶m); + + //disable CSN intterrupt + param = 0; + setSpiCtrlRegister(SPI_S_CS_UP_INT_EN, param); + //sddev_control(SPI_DEV_NAME, CMD_SPI_CS_EN, (void *)¶m); + + //clk test + //param = 5000000; + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKR, (void *)¶m); + + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi_master [CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi_master [CONFIG]:0x%08x \n", REG_READ(SPI_CONFIG)); +} + +int spidma_spi_master_dma_tx_init(UINT32 mode, UINT32 rate, struct spi_message *spi_msg) { + OSStatus result = 0; + + if (spi_dev) + spidma_spi_master_deinit(); + + spi_dev = os_malloc(sizeof(struct bk_spi_dev)); + if (!spi_dev) { + ADDLOG_ERROR(LOG_FEATURE_CMD, "[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_dev, 0, sizeof(struct bk_spi_dev)); + + result = rtos_init_semaphore(&spi_dev->dma_tx_sem, 1); + if (result != kNoErr) { + ADDLOG_ERROR(LOG_FEATURE_CMD, "[spi]: spi tx semp init failed\n"); + goto _exit; + } + + spidma_spi_master_dma_config(mode, rate); + + spidma_dma_master_tx_init(spi_msg); + spidma_dma_tx_enable(0); + set_txtrans_len((spi_msg->send_len)); + //sddev_control(SPI_DEV_NAME, CMD_SPI_TXTRANS_EN, (void *)&spi_msg->send_len); + + spi_dev->init_dma_tx = 1; + spi_dev->tx_ptr = spi_msg->send_buf; + spi_dev->tx_len = spi_msg->send_len; + + return 0; + +_exit: + + spidma_spi_master_deinit(); + + return 1; +} + + +int spidma_spi_master_dma_send(struct spi_message *spi_msg) { + int ret = 0; + + GLOBAL_INT_DECLARATION(); + ASSERT(spi_msg != NULL); + if (spi_dev->init_dma_tx == 0 || spi_dev == NULL) { + ADDLOG_ERROR(LOG_FEATURE_CMD, "spi_dma_send_ no init!\n"); + return -1; + } + if (spi_dev->flag & TX_FINISH_FLAG) { + ADDLOG_ERROR(LOG_FEATURE_CMD, "spi_dma_send_ TX_FINISH_FLAG!\n"); + return -2; + } + + if (spi_dev->tx_ptr != spi_msg->send_buf) { + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi_dma_send_ set pointer!\n"); + + GDMA_CFG_ST en_cfg; + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = (UINT32)spi_msg->send_buf; // dma dst addr + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_SRC_START_ADDR, (void *)&en_cfg); + spi_dev->tx_ptr = spi_msg->send_buf; + } + if (spi_dev->tx_len != spi_msg->send_len) { + ADDLOG_DEBUG(LOG_FEATURE_CMD, "spi_dma_send_ set length!\n"); + + GDMA_CFG_ST en_cfg; + //spi_ctrl(CMD_SPI_TXTRANS_EN, (void *)&spi_msg->send_len); + set_txtrans_len((spi_msg->send_len)); + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = spi_msg->send_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + spi_dev->tx_len = spi_msg->send_len; + } + + GLOBAL_INT_DISABLE(); + spi_dev->flag |= TX_FINISH_FLAG; + GLOBAL_INT_RESTORE(); + ADDLOG_ERROR(LOG_FEATURE_CMD, "before enable tx 0x%08x\r\n", REG_READ(SPI_CONFIG)); + + spidma_dma_tx_enable(1); + ADDLOG_ERROR(LOG_FEATURE_CMD, "enable tx 0x%08x\r\n", REG_READ(SPI_CONFIG)); + /* wait tx finish */ + //if (user_dma_tx_finish_callback == NULL) { + //因为写DMA是主动操作,所以DMA传输完成后,SPI不一定发送完成了。 + + rtos_get_semaphore(&spi_dev->dma_tx_sem, BEKEN_NEVER_TIMEOUT); + ret = spi_dev->flag; + //ADDLOG_ERROR(LOG_FEATURE_CMD, "rtos_semaphore ret 0x%08x \n", ret); + //} else + //ret = 0; + + if (spi_msg->send_buf != NULL) + return ret; + else { + ADDLOG_ERROR(LOG_FEATURE_CMD, "spi_dma tx error send_buff\r\n", spi_msg->send_buf); + return -3; + } +} +void spidma_master_dma_tx_disable(void) { + spidma_dma_tx_enable(0); + spi_dev->flag &= (~TX_FINISH_FLAG); +} + +void SPIDMA_Init(struct spi_message *spi_msg) { + uint32_t val; + + val = GFUNC_MODE_SPI_USE_GPIO_14; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); + + val = GFUNC_MODE_SPI_USE_GPIO_16_17; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); + + UINT32 param; + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + + param = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + + spidma_spi_master_dma_tx_init(0, 3000000, spi_msg); +} + +void SPIDMA_StartTX(struct spi_message *spi_msg) { + spidma_spi_master_dma_send(spi_msg); +} + +void SPIDMA_StopTX() { + spidma_master_dma_tx_disable(); +} + +#endif diff --git a/src/driver/drv_spidma.h b/src/driver/drv_spidma.h new file mode 100644 index 000000000..3461711fe --- /dev/null +++ b/src/driver/drv_spidma.h @@ -0,0 +1,39 @@ +#pragma once + +#include "../new_common.h" +#include "spi_pub.h" + +#define SPI_TX_DMA_CHANNEL GDMA_CHANNEL_3 + +#define SPI_PERI_CLK_26M (26 * 1000 * 1000) +#define SPI_PERI_CLK_DCO (120 * 1000 * 1000) + +#define SPI_BASE (0x00802700) +#define SPI_DAT (SPI_BASE + 3 * 4) +#define SPI_CONFIG (SPI_BASE + 0x1 * 4) +#define SPI_TX_EN (0x01UL << 0) + +struct bk_spi_dev { + uint8_t init_spi : 1; + uint8_t init_dma_tx : 1; + uint8_t init_dma_rx : 1; + uint8_t undef : 5; + + uint8_t *tx_ptr; + uint8_t *rx_ptr; + uint32_t tx_len; + uint32_t rx_len; + beken_semaphore_t tx_sem; + beken_semaphore_t rx_sem; + beken_semaphore_t dma_rx_sem; + beken_semaphore_t dma_tx_sem; + beken_mutex_t mutex; + uint32_t rx_offset; + uint32_t rx_drop; + uint32_t total_len; + volatile uint32_t flag; +}; + +void SPIDMA_Init(struct spi_message *spi_msg); +void SPIDMA_StartTX(struct spi_message *spi_msg); +void SPIDMA_StopTX(void); diff --git a/src/driver/drv_ssdp.c b/src/driver/drv_ssdp.c index 438fe00a3..5157df62b 100644 --- a/src/driver/drv_ssdp.c +++ b/src/driver/drv_ssdp.c @@ -232,6 +232,7 @@ static const char message_template[] = ; void DRV_WEMO_Send_Advert_To(int mode, struct sockaddr_in *addr); +void DRV_HUE_Send_Advert_To(struct sockaddr_in *addr); void DRV_SSDP_SendReply(struct sockaddr_in *addr, const char *message) { @@ -519,6 +520,7 @@ void DRV_SSDP_RunQuickTick() { if (!strncmp(udp_msgbuf, "M-SEARCH", 8)){ // reply with our advert to the sender addLogAdv(LOG_EXTRADEBUG, LOG_FEATURE_HTTP,"Is MSEARCH - responding"); +#if ENABLE_DRIVER_WEMO if (DRV_IsRunning("WEMO")) { if (strcasestr(udp_msgbuf, "urn:belkin:device:**")) { DRV_WEMO_Send_Advert_To(1, &addr); @@ -531,6 +533,20 @@ void DRV_SSDP_RunQuickTick() { return; } } +#endif +#if ENABLE_DRIVER_HUE + if (DRV_IsRunning("HUE")) { + if (strcasestr(udp_msgbuf, ":device:basic:1") + || strcasestr(udp_msgbuf, "upnp:rootdevice") + || strcasestr(udp_msgbuf, "ssdpsearch:all") + || strcasestr(udp_msgbuf, "ssdp:all")) { + addLogAdv(LOG_ALL, LOG_FEATURE_HTTP, "SSDP has received HUE PACKET"); + addLogAdv(LOG_ALL, LOG_FEATURE_HTTP, udp_msgbuf); + DRV_HUE_Send_Advert_To(&addr); + return; + } + } +#endif DRV_SSDP_Send_Advert_To(&addr); } diff --git a/src/driver/drv_tuyaMCU.c b/src/driver/drv_tuyaMCU.c index f08357a3c..01180c8be 100644 --- a/src/driver/drv_tuyaMCU.c +++ b/src/driver/drv_tuyaMCU.c @@ -25,6 +25,7 @@ https://developer.tuya.com/en/docs/iot/tuyacloudlowpoweruniversalserialaccesspro #include "drv_public.h" #include #include "drv_ntp.h" +#include "../rgb2hsv.h" #define TUYA_CMD_HEARTBEAT 0x00 @@ -189,6 +190,10 @@ static int g_sendQueryStatePackets = 0; // See: https://imgur.com/a/mEfhfiA static byte g_defaultTuyaMCUWiFiState = 0x00; +// LED lighitng +// See: https://www.elektroda.com/rtvforum/viewtopic.php?p=20646359#20646359 +static short g_tuyaMCUled_dpID = -1; +static short g_tuyaMCUled_format = -1; // battery powered device state enum TuyaMCUV0State { @@ -341,34 +346,71 @@ void TuyaMCU_SendCommandWithData(byte cmdType, byte* data, int payload_len) { } UART_SendByte(check_sum); } +int TuyaMCU_AppendStateInternal(byte *buffer, int bufferMax, int currentLen, uint8_t id, int8_t type, void* value, int dataLen) { + if (currentLen + 4 + dataLen >= bufferMax) { + addLogAdv(LOG_ERROR, LOG_FEATURE_TUYAMCU, "Tuya buff overflow"); + return 0; + } + buffer[currentLen + 0] = id; + buffer[currentLen + 1] = type; + buffer[currentLen + 2] = 0x00; + buffer[currentLen + 3] = dataLen; + memcpy(buffer + (currentLen + 4), value, dataLen); + return currentLen + 4 + dataLen; +} +void TuyaMCU_SendStateInternal(uint8_t id, uint8_t type, void* value, int dataLen) +{ + uint16_t payload_len = 0; + uint8_t payload_buffer[32]; + + payload_len = TuyaMCU_AppendStateInternal(payload_buffer, sizeof(payload_buffer), + payload_len, id, type, value, dataLen); + TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} +void TuyaMCU_SendTwoVals(byte idA, int valA, byte idB, int valB) +{ + byte swap[4]; + uint16_t payload_len = 0; + uint8_t payload_buffer[32]; + + swap[0] = ((byte*)&valA)[3]; + swap[1] = ((byte*)&valA)[2]; + swap[2] = ((byte*)&valA)[1]; + swap[3] = ((byte*)&valA)[0]; + payload_len = TuyaMCU_AppendStateInternal(payload_buffer, sizeof(payload_buffer), + payload_len, idA, DP_TYPE_VALUE, swap, 4); + swap[0] = ((byte*)&valB)[3]; + swap[1] = ((byte*)&valB)[2]; + swap[2] = ((byte*)&valB)[1]; + swap[3] = ((byte*)&valB)[0]; + payload_len = TuyaMCU_AppendStateInternal(payload_buffer, sizeof(payload_buffer), + payload_len, idB, DP_TYPE_VALUE, swap, 4); + + TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} void TuyaMCU_SendState(uint8_t id, uint8_t type, uint8_t* value) { - uint16_t payload_len = 4; - uint8_t payload_buffer[8]; - payload_buffer[0] = id; - payload_buffer[1] = type; + byte swap[4]; + switch (type) { case DP_TYPE_BOOL: case DP_TYPE_ENUM: - payload_len += 1; - payload_buffer[2] = 0x00; - payload_buffer[3] = 0x01; - payload_buffer[4] = value[0]; + TuyaMCU_SendStateInternal(id, type, value, 1); break; case DP_TYPE_VALUE: - payload_len += 4; - payload_buffer[2] = 0x00; - payload_buffer[3] = 0x04; - payload_buffer[4] = value[3]; - payload_buffer[5] = value[2]; - payload_buffer[6] = value[1]; - payload_buffer[7] = value[0]; + swap[0] = value[3]; + swap[1] = value[2]; + swap[2] = value[1]; + swap[3] = value[0]; + TuyaMCU_SendStateInternal(id, type, swap, 4); + break; + case DP_TYPE_STRING: + TuyaMCU_SendStateInternal(id, type, value, strlen((const char*)value)); + break; + case DP_TYPE_RAW: break; - } - - TuyaMCU_SendCommandWithData(TUYA_CMD_SET_DP, payload_buffer, payload_len); } void TuyaMCU_SendBool(uint8_t id, bool value) @@ -494,6 +536,67 @@ commandResult_t Cmd_TuyaMCU_Set_DefaultWiFiState(const void* context, const char return CMD_RES_OK; } +void TuyaMCU_SendColor(int dpID, float fR, float fG, float fB, int tuyaRGB) { + char str[16]; + float hue, sat, val; + + RGBtoHSV(fR, fG, fB, &hue, &sat, &val); + int iHue, iSat, iVal; + iHue = (int)hue; //0,359 + iSat = sat * 100; // 0-100 + iVal = val * 100; // 0-100 + + // this is based on formats figured out in Tasmota + switch (tuyaRGB) { + case 0: // Uppercase Type 1 payload + sprintf(str, "%04X%04X%04X", iHue, iSat * 10, iVal * 10); + break; + case 1: // Lowercase Type 1 payload + sprintf(str, "%04x%04x%04x", iHue, iSat * 10, iVal * 10); + break; + case 2: // Uppercase Type 2 payload + //snprintf(str, sizeof(str), ("%sFFFF6464"), scolor); + break; + case 3: // Lowercase Type 2 payload + //snprintf(str, sizeof(str), ("%sffff6464"), tolower(scolor, scolor)); + break; + } + addLogAdv(LOG_INFO, LOG_FEATURE_TUYAMCU, "Color is sent as %s\n", str); + TuyaMCU_SendString(dpID, str); +} +// tuyaMCU_sendColor dpID red01 green01 blue01 tuyaRGB +// tuyaMCU_sendColor 24 1 0 0 1 +// tuyaMCU_sendColor 24 1 0 0 1 +commandResult_t Cmd_TuyaMCU_SendColor(const void* context, const char* cmd, const char* args, int cmdFlags) { + int toSend; + float fR, fG, fB; + int dpID, tuyaRGB; + + Tokenizer_TokenizeString(args, 0); + + dpID = Tokenizer_GetArgInteger(0); + fR = Tokenizer_GetArgFloat(1); + fG = Tokenizer_GetArgFloat(2); + fB = Tokenizer_GetArgFloat(3); + tuyaRGB = Tokenizer_GetArgIntegerDefault(4, 1); + + TuyaMCU_SendColor(dpID, fR, fG, fB, tuyaRGB); + + return CMD_RES_OK; +} +// tuyaMCU_setupLED dpID TasFormat +commandResult_t Cmd_TuyaMCU_SetupLED(const void* context, const char* cmd, const char* args, int cmdFlags) { + + Tokenizer_TokenizeString(args, 0); + if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) { + return CMD_RES_NOT_ENOUGH_ARGUMENTS; + } + + g_tuyaMCUled_dpID = Tokenizer_GetArgInteger(0); + g_tuyaMCUled_format = Tokenizer_GetArgInteger(1); + + return CMD_RES_OK; +} commandResult_t Cmd_TuyaMCU_Send_RSSI(const void* context, const char* cmd, const char* args, int cmdFlags) { int toSend; @@ -718,11 +821,79 @@ commandResult_t TuyaMCU_SendQueryState(const void* context, const char* cmd, con return CMD_RES_OK; } +void TuyaMCU_SendStateRawFromString(int dpId, const char *args) { + const char *stop; + float val; + int cur = 0; + byte buffer[64]; + while (*args) { + if (cur >= sizeof(buffer)) { + addLogAdv(LOG_ERROR, LOG_FEATURE_TUYAMCU, "Tuya raw buff overflow"); + return; + } + if (*args == ' ') { + args++; + continue; + } + if (*args == '$') { + stop = args + 1; + while (*stop && *stop != '$') { + stop++; + } + CMD_ExpandConstant(args, stop, &val); + buffer[cur] = (int)val; + cur++; + + if (*stop == 0) + break; + args = stop + 1; + continue; + } + + buffer[cur] = hexbyte(args); + cur++; + + args += 2; + } + TuyaMCU_SendStateInternal(dpId, DP_TYPE_RAW, buffer, cur); +} +const char *STR_FindArg(const char *s, int arg) { + while (1) { + while (isspace(*s)) { + if (*s == 0) + return ""; + s++; + } + arg--; + if (arg < 0) { + return s; + } + while (isspace(*s) == false) { + if (*s == 0) + return ""; + s++; + } + } + return 0; +} +// tuyaMcu_sendState id type value +// send boolean true +// tuyaMcu_sendState 25 1 1 +// send boolean false +// tuyaMcu_sendState 25 1 0 +// send value 87 +// tuyaMcu_sendState 25 2 87 +// send string +// tuyaMcu_sendState 25 3 ff0000646464ff +// send raw +// tuyaMcu_sendState 25 4 ff$CH3$00646464ff +// tuyaMcu_sendState 2 1 0404010C$CH9$$CH10$$CH11$FF04FEFF0031 commandResult_t TuyaMCU_SendStateCmd(const void* context, const char* cmd, const char* args, int cmdFlags) { int dpId; int dpType; int value; + const char *valStr; Tokenizer_TokenizeString(args, 0); // following check must be done after 'Tokenizer_TokenizeString', @@ -734,9 +905,19 @@ commandResult_t TuyaMCU_SendStateCmd(const void* context, const char* cmd, const dpId = Tokenizer_GetArgInteger(0); dpType = Tokenizer_GetArgInteger(1); - value = Tokenizer_GetArgInteger(2); - - TuyaMCU_SendState(dpId, dpType, (uint8_t*)&value); + if (dpType == DP_TYPE_STRING) { + valStr = Tokenizer_GetArg(2); + TuyaMCU_SendState(dpId, DP_TYPE_STRING, (uint8_t*)valStr); + } + else if (dpType == DP_TYPE_RAW) { + //valStr = Tokenizer_GetArg(2); + valStr = STR_FindArg(args, 2); + TuyaMCU_SendStateRawFromString(dpId, valStr); + } + else { + value = Tokenizer_GetArgInteger(2); + TuyaMCU_SendState(dpId, dpType, (uint8_t*)&value); + } return CMD_RES_OK; } @@ -1208,7 +1389,7 @@ void TuyaMCU_V0_SendDPCacheReply() { // 12 02 0004 00000001 // fnId = 18 Len = 0004 Val V = 1 // - while(map) { + while (map) { if (map->bDPCache) { writtenCount++; // dpID @@ -1326,7 +1507,8 @@ void TuyaMCU_ProcessIncoming(const byte* data, int len) { if (g_sensorMode) { if (g_tuyaBatteryPoweredState == TM0_STATE_AWAITING_WIFI) { g_tuyaBatteryPoweredState = TM0_STATE_AWAITING_MQTT; - } else if (g_tuyaBatteryPoweredState == TM0_STATE_AWAITING_MQTT) { + } + else if (g_tuyaBatteryPoweredState == TM0_STATE_AWAITING_MQTT) { g_tuyaBatteryPoweredState = TM0_STATE_AWAITING_STATES; g_tuyaNextRequestDelay = 0; } @@ -1371,10 +1553,10 @@ void TuyaMCU_ProcessIncoming(const byte* data, int len) { case TUYA_V0_CMD_OBTAINDPCACHE: // This is sent by TH01 // Info:TuyaMCU:TUYAMCU received: 55 AA 00 10 00 02 01 09 1B - { - TuyaMCU_V0_SendDPCacheReply(); - } - break; + { + TuyaMCU_V0_SendDPCacheReply(); + } + break; case 0x05: // This was added for this user: // https://www.elektroda.com/rtvforum/topic3937723.html @@ -1665,7 +1847,47 @@ commandResult_t TuyaMCU_SetBaudRate(const void* context, const char* cmd, const return CMD_RES_OK; } +void TuyaMCU_OnRGBCWChange(const float *rgbcw, int bLightEnableAll, int iLightMode, float brightnessRange01, float temperatureRange01) { + if (g_tuyaMCUled_dpID == -1) { + return; + } + // dpID 20: switch light on and off + TuyaMCU_SendBool(20, bLightEnableAll); + if (bLightEnableAll == false) { + // nothing else to do! + return; + } + rtos_delay_milliseconds(50); + if (iLightMode == Light_RGB) { + // dpID 21: switch between RGB and white mode : 0->white, 1->RGB + TuyaMCU_SendBool(21, 1); + rtos_delay_milliseconds(50); + // dpID 24: color(and indirectly brightness) in RGB mode, handled by your code already fine + TuyaMCU_SendColor(g_tuyaMCUled_dpID, rgbcw[0] / 255.0f, rgbcw[1] / 255.0f, rgbcw[2] / 255.0f, g_tuyaMCUled_format); + } + else { + // dpID 21: switch between RGB and white mode : 0->white, 1->RGB + //TuyaMCU_SendBool(21, 0); + // dpID 22: brightness only in white mode: The range is from 50 (dark) to 1000 (light), + // NOTE: when changing this value, dpID 21 is set to 0 -> white automatically + int mcu_brightness = brightnessRange01 * 1000.0f; + TuyaMCU_SendValue(22, mcu_brightness); + rtos_delay_milliseconds(50); + // dpID 23: Kelvin value of white : The range is from 10 (ww)to 990 (cw), + // NOTE : when changing this value, dpID 21 is set to 0->white automatically + int mcu_temperature = 10 + temperatureRange01 * 980.0f; + TuyaMCU_SendValue(23, mcu_temperature); + //TuyaMCU_SendTwoVals(22, mcu_brightness, 23, mcu_temperature); + } + + +} +bool TuyaMCU_IsLEDRunning() { + if (g_tuyaMCUled_dpID == -1) + return false; + return true; +} void TuyaMCU_Init() { @@ -1681,7 +1903,7 @@ void TuyaMCU_Init() g_resetWiFiEvents = 0; g_tuyaNextRequestDelay = 1; - g_tuyaBatteryPoweredState = 0; + g_tuyaBatteryPoweredState = 0; g_tuyaMCUConfirmationsToSend_0x05 = 0; g_tuyaMCUConfirmationsToSend_0x08 = 0; @@ -1754,8 +1976,22 @@ void TuyaMCU_Init() //cmddetail:"fn":"Cmd_TuyaMCU_Send_RSSI","file":"driver/drv_tuyaMCU.c","requires":"", //cmddetail:"examples":""} CMD_RegisterCommand("tuyaMcu_defWiFiState", Cmd_TuyaMCU_Set_DefaultWiFiState, NULL); + + //cmddetail:{"name":"tuyaMcu_sendColor","args":"Cmd_TuyaMCU_SendColor", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_tuyaMCU.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("tuyaMcu_sendColor", Cmd_TuyaMCU_SendColor, NULL); + + //cmddetail:{"name":"tuyaMcu_setupLED","args":"Cmd_TuyaMCU_SetupLED", + //cmddetail:"descr":"", + //cmddetail:"fn":"NULL);","file":"driver/drv_tuyaMCU.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("tuyaMcu_setupLED", Cmd_TuyaMCU_SetupLED, NULL); } + + // Door sensor with TuyaMCU version 0 (not 3), so all replies have x00 and not 0x03 byte // fakeTuyaPacket 55AA0008000C00010101010101030400010223 // fakeTuyaPacket 55AA0008000C00020202020202010100010123 diff --git a/src/hal/bk7231/hal_adc_bk7231.c b/src/hal/bk7231/hal_adc_bk7231.c index 480d86772..5c4260bac 100644 --- a/src/hal/bk7231/hal_adc_bk7231.c +++ b/src/hal/bk7231/hal_adc_bk7231.c @@ -17,12 +17,12 @@ void turnon_PA_in_temp_dect(void); static int adcToGpio[] = { -1, // ADC0 - VBAT - 4, //GPIO4, // ADC1 - 5, //GPIO5, // ADC2 + 26, //GPIO26, // ADC1 + 24, //GPIO24, // ADC2 23,//GPIO23, // ADC3 - 2,//GPIO2, // ADC4 - 3,//GPIO3, // ADC5 - 12,//GPIO12, // ADC6 + 28,//GPIO28, // ADC4 + 22,//GPIO22, // ADC5 + 21,//GPIO21, // ADC6 13,//GPIO13, // ADC7 }; static int c_adcToGpio = sizeof(adcToGpio)/sizeof(adcToGpio[0]); diff --git a/src/hal/w800/hal_pins_w800.c b/src/hal/w800/hal_pins_w800.c index de6ddb27f..f03948bbb 100644 --- a/src/hal/w800/hal_pins_w800.c +++ b/src/hal/w800/hal_pins_w800.c @@ -170,9 +170,17 @@ static int pwm_demo_multiplex_config(u8 channel) switch (channel) { case 0: + wm_pwm1_config(g_pwmChannelPins[channel]); + break; case 1: + wm_pwm2_config(g_pwmChannelPins[channel]); + break; case 2: + wm_pwm3_config(g_pwmChannelPins[channel]); + break; case 3: + wm_pwm4_config(g_pwmChannelPins[channel]); + break; case 4: wm_pwm5_config(g_pwmChannelPins[channel]); break; diff --git a/src/hal/win32/hal_wifi_win32.c b/src/hal/win32/hal_wifi_win32.c index 3641c56c8..f14e2c271 100644 --- a/src/hal/win32/hal_wifi_win32.c +++ b/src/hal/win32/hal_wifi_win32.c @@ -18,7 +18,12 @@ static char g_ipStr[32]; void HAL_ConnectToWiFi(const char *ssid, const char *psk, obkStaticIP_t *ip) { - g_wifiStatusCallback(WIFI_STA_CONNECTED); + if (g_wifiStatusCallback) { + g_wifiStatusCallback(WIFI_STA_CONNECTED); + } + else { + printf("Win32 simulator - not calling g_wifiStatusCallback because it's null\n"); + } } void HAL_DisconnectFromWifi() diff --git a/src/httpserver/hass.c b/src/httpserver/hass.c index 05ff770cc..d059c1f64 100644 --- a/src/httpserver/hass.c +++ b/src/httpserver/hass.c @@ -67,6 +67,9 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) { case CO2_SENSOR: sprintf(uniq_id, "%s_%s_%d", longDeviceName, "co2", index); break; + case ILLUMINANCE_SENSOR: + sprintf(uniq_id, "%s_%s_%d", longDeviceName, "illuminance", index); + break; case SMOKE_SENSOR: sprintf(uniq_id, "%s_%s_%d", longDeviceName, "smoke", index); break; @@ -235,6 +238,9 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, char* payload case VOLTAGE_SENSOR: sprintf(g_hassBuffer, "%s Voltage", CFG_GetShortDeviceName()); break; + case ILLUMINANCE_SENSOR: + sprintf(g_hassBuffer, "%s Illuminance", CFG_GetShortDeviceName()); + break; default: sprintf(g_hassBuffer, "%s %s", CFG_GetShortDeviceName(), CHANNEL_GetLabel(index)); break; @@ -499,6 +505,12 @@ HassDeviceInfo* hass_init_sensor_device_info(ENTITY_TYPE type, int channel, int sprintf(g_hassBuffer, "~/%d/get", channel); cJSON_AddStringToObject(info->root, "stat_t", g_hassBuffer); break; + case ILLUMINANCE_SENSOR: + cJSON_AddStringToObject(info->root, "dev_cla", "illuminance"); + cJSON_AddStringToObject(info->root, "unit_of_meas", "lx"); + sprintf(g_hassBuffer, "~/%d/get", channel); + cJSON_AddStringToObject(info->root, "stat_t", g_hassBuffer); + break; case BATTERY_SENSOR: cJSON_AddStringToObject(info->root, "dev_cla", "battery"); cJSON_AddStringToObject(info->root, "unit_of_meas", "%"); @@ -527,6 +539,13 @@ HassDeviceInfo* hass_init_sensor_device_info(ENTITY_TYPE type, int channel, int sprintf(g_hassBuffer, "~/%d/get", channel); cJSON_AddStringToObject(info->root, "stat_t", g_hassBuffer); break; + case ENERGY_SENSOR: + cJSON_AddStringToObject(info->root, "dev_cla", "energy"); + cJSON_AddStringToObject(info->root, "unit_of_meas", "kWh"); + sprintf(g_hassBuffer, "~/%d/get", channel); + cJSON_AddStringToObject(info->root, "stat_cla", "total_increasing"); + cJSON_AddStringToObject(info->root, "stat_t", g_hassBuffer); + break; case POWERFACTOR_SENSOR: cJSON_AddStringToObject(info->root, "dev_cla", "power_factor"); //cJSON_AddStringToObject(info->root, "unit_of_meas", "W"); @@ -555,7 +574,7 @@ HassDeviceInfo* hass_init_sensor_device_info(ENTITY_TYPE type, int channel, int return NULL; } - if (type != READONLYLOWMIDHIGH_SENSOR) { + if (type != READONLYLOWMIDHIGH_SENSOR && type != ENERGY_SENSOR) { cJSON_AddStringToObject(info->root, "stat_cla", "measurement"); } diff --git a/src/httpserver/hass.h b/src/httpserver/hass.h index f6fc1a345..49638bb35 100644 --- a/src/httpserver/hass.h +++ b/src/httpserver/hass.h @@ -61,6 +61,10 @@ typedef enum { SMOKE_SENSOR, /// @brief READONLYLOWMIDHIGH_SENSOR, + // lx unit + ILLUMINANCE_SENSOR, + + ENERGY_SENSOR, } ENTITY_TYPE; //unique_id is defined in hass_populate_unique_id and is based on CFG_GetDeviceName() whose size is CGF_DEVICE_NAME_SIZE. diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c index 15b040b6b..b303243bf 100644 --- a/src/httpserver/http_fns.c +++ b/src/httpserver/http_fns.c @@ -480,6 +480,13 @@ int http_fn_index(http_request_t* request) { poststr(request, ""); } + else if (channelType == ChType_Illuminance) { + iValue = CHANNEL_Get(i); + + poststr(request, ""); + hprintf255(request, "Illuminance (%s) = %i Lux", CHANNEL_GetLabel(i), iValue); + poststr(request, ""); + } else if (channelType == ChType_ReadOnly) { iValue = CHANNEL_Get(i); @@ -1866,6 +1873,15 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) { discoveryQueued = true; } break; + case ChType_Illuminance: + { + dev_info = hass_init_sensor_device_info(ILLUMINANCE_SENSOR, i, -1, -1); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + + discoveryQueued = true; + } + break; case ChType_ReadOnly: { dev_info = hass_init_sensor_device_info(CUSTOM_SENSOR, i, -1, -1); @@ -1965,6 +1981,24 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) { discoveryQueued = true; } break; + case ChType_EnergyTotal_kWh_div100: + { + dev_info = hass_init_sensor_device_info(ENERGY_SENSOR, i, 3, 2); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + + discoveryQueued = true; + } + break; + case ChType_EnergyTotal_kWh_div1000: + { + dev_info = hass_init_sensor_device_info(ENERGY_SENSOR, i, 3, 3); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + + discoveryQueued = true; + } + break; } } #endif @@ -2478,7 +2512,7 @@ const char* g_obk_flagNames[] = { "[Power] Set power and current to zero if all relays are open", "[MQTT] [Debug] Publish all channels (don't enable it, it will be publish all 64 possible channels on connect)", "[MQTT] Use kWh unit for energy consumption (total, last hour, today) instead of Wh", - "error", + "[BTN] Ignore all button events (aka child lock)", "error", "error", "error", diff --git a/src/httpserver/http_tcp_server_nonblocking.c b/src/httpserver/http_tcp_server_nonblocking.c index 1408ae00b..40339b7da 100644 --- a/src/httpserver/http_tcp_server_nonblocking.c +++ b/src/httpserver/http_tcp_server_nonblocking.c @@ -10,7 +10,7 @@ SOCKET ListenSocket = INVALID_SOCKET; -int g_port = 80; +int g_httpPort = 80; int HTTPServer_Start() { @@ -30,7 +30,7 @@ int HTTPServer_Start() { } // Resolve the server address and port char service[6]; - snprintf(service, sizeof(service), "%u", g_port); + snprintf(service, sizeof(service), "%u", g_httpPort); iResult = getaddrinfo(NULL, service, &hints, &result); if ( iResult != 0 ) { diff --git a/src/httpserver/json_interface.c b/src/httpserver/json_interface.c index 0108249d3..0f854adf7 100644 --- a/src/httpserver/json_interface.c +++ b/src/httpserver/json_interface.c @@ -937,6 +937,14 @@ int JSON_ProcessCommandReply(const char* cmd, const char* arg, void* request, js MQTT_PublishPrinterContentsToStat((struct obk_mqtt_publishReplyPrinter_s*)request, "STATUS4"); } } + else if (!stricmp(arg, "11")) { + printer(request, "{"); + http_tasmota_json_status_STS(request, printer, true); + printer(request, "}"); + if (flags == COMMAND_FLAG_SOURCE_MQTT) { + MQTT_PublishPrinterContentsToStat((struct obk_mqtt_publishReplyPrinter_s*)request, "STATUS11"); + } + } else if (!stricmp(arg, "2")) { printer(request, "{"); http_tasmota_json_status_FWR(request, printer); diff --git a/src/httpserver/new_http.c b/src/httpserver/new_http.c index c5b91a5b4..f936a72fe 100644 --- a/src/httpserver/new_http.c +++ b/src/httpserver/new_http.c @@ -459,6 +459,10 @@ const char* htmlPinRoleNames[] = { "TM1638_DAT", "TM1638_STB", "BAT_Relay_n", + "KP18058_CLK", + "KP18058_DAT", + "error", + "error", "error", "error", }; @@ -573,6 +577,7 @@ int hprintf255(http_request_t* request, const char* fmt, ...) { return postany(request, tmp, strlen(tmp)); } +int HUE_APICall(http_request_t* request); int HTTP_ProcessPacket(http_request_t* request) { int i; @@ -698,6 +703,12 @@ int HTTP_ProcessPacket(http_request_t* request) { return http_fn_empty_url(request); #endif +#if ENABLE_DRIVER_HUE + if (HUE_APICall(request)) { + return 0; + } +#endif + // look for a callback with this URL and method, or HTTP_ANY for (i = 0; i < numCallbacks; i++) { char* url = callbacks[i]->url; diff --git a/src/httpserver/rest_interface.c b/src/httpserver/rest_interface.c index f8e42bf15..9347f3197 100644 --- a/src/httpserver/rest_interface.c +++ b/src/httpserver/rest_interface.c @@ -348,6 +348,7 @@ static int http_rest_get_lfs_file(http_request_t* request) { int lfsres; int total = 0; lfs_file_t* file; + char *args; // don't start LFS just because we're trying to read a file - // it won't exist anyway @@ -366,6 +367,12 @@ static int http_rest_get_lfs_file(http_request_t* request) { strcpy(fpath, request->url + strlen("api/lfs/")); + // strip HTTP args with ? + args = strchr(fpath, '?'); + if (args) { + *args = 0; + } + ADDLOG_DEBUG(LOG_FEATURE_API, "LFS read of %s", fpath); lfsres = lfs_file_open(&lfs, file, fpath, LFS_O_RDONLY); diff --git a/src/new_cfg.c b/src/new_cfg.c index 27eb215d6..b685ad491 100644 --- a/src/new_cfg.c +++ b/src/new_cfg.c @@ -26,7 +26,11 @@ int g_cfg_pendingChanges = 0; #define MAIN_CFG_VERSION_V3 3 // version 4 - bumped size by 1024, // added alternate ssid fields +#if PLATFORM_W600 +#define MAIN_CFG_VERSION 3 +#else #define MAIN_CFG_VERSION 4 +#endif static byte CFG_CalcChecksum(mainConfig_t *inf) { int header_size; @@ -38,11 +42,14 @@ static byte CFG_CalcChecksum(mainConfig_t *inf) { if (inf->version == MAIN_CFG_VERSION_V3) { configSize = MAGIC_CONFIG_SIZE_V3; +#if ALLOW_SSID2 // quick fix for converting inf->wifi_pass2[0] = 0; inf->wifi_ssid2[0] = 0; +#endif } - else { + else + { configSize = sizeof(mainConfig_t); } remaining_size = configSize - header_size; @@ -322,10 +329,18 @@ const char *CFG_GetWiFiPass(){ return wifi_pass; } const char *CFG_GetWiFiSSID2() { +#if ALLOW_SSID2 return g_cfg.wifi_ssid2; +#else + return ""; +#endif } const char *CFG_GetWiFiPass2() { +#if ALLOW_SSID2 return g_cfg.wifi_pass2; +#else + return ""; +#endif } int CFG_SetWiFiSSID(const char *s) { // this will return non-zero if there were any changes @@ -351,20 +366,24 @@ int CFG_SetWiFiPass(const char *s) { return 0; } int CFG_SetWiFiSSID2(const char *s) { +#if ALLOW_SSID2 // this will return non-zero if there were any changes if (strcpy_safe_checkForChanges(g_cfg.wifi_ssid2, s, sizeof(g_cfg.wifi_ssid2))) { // mark as dirty (value has changed) g_cfg_pendingChanges++; return 1; } +#endif return 0; } int CFG_SetWiFiPass2(const char *s) { +#if ALLOW_SSID2 if (strcpy_safe_checkForChanges(g_cfg.wifi_pass2, s, sizeof(g_cfg.wifi_pass2))) { // mark as dirty (value has changed) g_cfg_pendingChanges++; return 1; } +#endif return 0; } const char *CFG_GetMQTTHost() { diff --git a/src/new_pins.c b/src/new_pins.c index e0d3c029f..72feaf6ff 100644 --- a/src/new_pins.c +++ b/src/new_pins.c @@ -326,12 +326,22 @@ void RAW_SetPinValue(int index, int iVal) { } } void Button_OnPressRelease(int index) { + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } // fire event - button on pin was released EventHandlers_FireEvent(CMD_EVENT_PIN_ONRELEASE, index); } void Button_OnInitialPressDown(int index) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "%i Button_OnInitialPressDown\r\n", index); + + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } + EventHandlers_FireEvent(CMD_EVENT_PIN_ONPRESS, index); // so-called SetOption13 - instant reaction to touch instead of waiting for release @@ -374,6 +384,10 @@ void Button_OnInitialPressDown(int index) void Button_OnShortClick(int index) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "%i key_short_press\r\n", index); + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } // fire event - button on pin was clicked EventHandlers_FireEvent(CMD_EVENT_PIN_ONCLICK, index); // so-called SetOption13 - instant reaction to touch instead of waiting for release @@ -414,6 +428,10 @@ void Button_OnShortClick(int index) void Button_OnDoubleClick(int index) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "%i key_double_press\r\n", index); + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } if (g_cfg.pins.roles[index] == IOR_Button_ToggleAll || g_cfg.pins.roles[index] == IOR_Button_ToggleAll_n) { CHANNEL_DoSpecialToggleAll(); @@ -439,6 +457,10 @@ void Button_OnDoubleClick(int index) void Button_OnTripleClick(int index) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "%i key_triple_press\r\n", index); + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } // fire event - button on pin was 3clicked EventHandlers_FireEvent(CMD_EVENT_PIN_ON3CLICK, index); if (g_cfg.pins.roles[index] == IOR_SmartButtonForLEDs || g_cfg.pins.roles[index] == IOR_SmartButtonForLEDs_n) { @@ -450,17 +472,29 @@ void Button_OnTripleClick(int index) void Button_OnQuadrupleClick(int index) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "%i key_quadruple_press\r\n", index); + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } // fire event - button on pin was 4clicked EventHandlers_FireEvent(CMD_EVENT_PIN_ON4CLICK, index); } void Button_On5xClick(int index) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "%i key_5x_press\r\n", index); + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } // fire event - button on pin was 4clicked EventHandlers_FireEvent(CMD_EVENT_PIN_ON5CLICK, index); } void Button_OnLongPressHold(int index) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "%i Button_OnLongPressHold\r\n", index); + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } // fire event - button on pin was held EventHandlers_FireEvent(CMD_EVENT_PIN_ONHOLD, index); @@ -478,6 +512,10 @@ void Button_OnLongPressHold(int index) { } void Button_OnLongPressHoldStart(int index) { addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "%i Button_OnLongPressHoldStart\r\n", index); + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + return; + } // fire event - button on pin was held EventHandlers_FireEvent(CMD_EVENT_PIN_ONHOLDSTART, index); } @@ -1711,10 +1749,17 @@ void PIN_ticks(void* param) if (g_lastValidState[i] != value) { // became up g_lastValidState[i] = value; - CHANNEL_Toggle(g_cfg.pins.channels[i]); - // fire event - IOR_ToggleChannelOnToggle has been toggle - // Argument is a pin number (NOT channel) - EventHandlers_FireEvent(CMD_EVENT_PIN_ONTOGGLE, i); + + + if (CFG_HasFlag(OBK_FLAG_BUTTON_DISABLE_ALL)) { + addLogAdv(LOG_INFO, LOG_FEATURE_GENERAL, "Child lock!"); + } + else { + CHANNEL_Toggle(g_cfg.pins.channels[i]); + // fire event - IOR_ToggleChannelOnToggle has been toggle + // Argument is a pin number (NOT channel) + EventHandlers_FireEvent(CMD_EVENT_PIN_ONTOGGLE, i); + } // lock for given time g_times[i] = debounceMS; } @@ -1815,7 +1860,7 @@ const char* g_channelTypeNames[] = { "Power_div10", "ReadOnlyLowMidHigh", "SmokePercent", - "error", + "Illuminance", "error", "error", "error", diff --git a/src/new_pins.h b/src/new_pins.h index c9c0482cd..afc31d2a1 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -537,13 +537,26 @@ typedef enum ioRole_e { //iodetail:"file":"new_pins.h", //iodetail:"driver":""} IOR_BAT_Relay_n, + //iodetail:{"name":"KP18058_CLK", + //iodetail:"title":"TODO", + //iodetail:"descr":"QQQ", + //iodetail:"enum":"KP18058_CLK", + //iodetail:"file":"new_pins.h", + //iodetail:"driver":""} + IOR_KP18058_CLK, + //iodetail:{"name":"KP18058_DAT", + //iodetail:"title":"TODO", + //iodetail:"descr":"QQQ", + //iodetail:"enum":"KP18058_DAT", + //iodetail:"file":"new_pins.h", + //iodetail:"driver":""} + IOR_KP18058_DAT, //iodetail:{"name":"Total_Options", //iodetail:"title":"TODO", //iodetail:"descr":"Current total number of available IOR roles", //iodetail:"enum":"IOR_Total_Options", //iodetail:"file":"new_pins.h", //iodetail:"driver":""} - IOR_Total_Options, } ioRole_t; @@ -818,6 +831,13 @@ typedef enum channelType_e { //chandetail:"file":"new_pins.h", //chandetail:"driver":""} ChType_SmokePercent, + //chandetail:{"name":"Illuminance", + //chandetail:"title":"TODO", + //chandetail:"descr":"Illuminance in Lux", + //chandetail:"enum":"ChType_Illuminance", + //chandetail:"file":"new_pins.h", + //chandetail:"driver":""} + ChType_Illuminance, //chandetail:{"name":"Max", //chandetail:"title":"TODO", @@ -942,8 +962,9 @@ typedef struct pinsState_s { #define OBK_FLAG_POWER_FORCE_ZERO_IF_RELAYS_OPEN 38 #define OBK_FLAG_MQTT_PUBLISH_ALL_CHANNELS 39 #define OBK_FLAG_MQTT_ENERGY_IN_KWH 40 +#define OBK_FLAG_BUTTON_DISABLE_ALL 41 -#define OBK_TOTAL_FLAGS 41 +#define OBK_TOTAL_FLAGS 42 #define LOGGER_FLAG_MQTT_DEDUPER 1 #define LOGGER_FLAG_POWER_SAVE 2 @@ -1118,6 +1139,11 @@ typedef struct mainConfig_s { char ping_host[64]; // ofs 0x000005E0 (dec 1504) //char initCommandLine[512]; +#if PLATFORM_W600 +#define ALLOW_SSID2 0 + char initCommandLine[512]; +#else +#define ALLOW_SSID2 1 char initCommandLine[1568]; // offset 0x00000C00 (3072 decimal) char wifi_ssid2[64]; @@ -1125,6 +1151,7 @@ typedef struct mainConfig_s { char wifi_pass2[68]; // offset 0x00000C84 (3204 decimal) char unused[380]; +#endif } mainConfig_t; // one sector is 4096 so it we still have some expand possibility diff --git a/src/obk_config.h b/src/obk_config.h index b35aa13a9..be9d4c841 100644 --- a/src/obk_config.h +++ b/src/obk_config.h @@ -38,6 +38,8 @@ #define ENABLE_DRIVER_BL0942 1 #define ENABLE_DRIVER_BL0942SPI 1 #define ENABLE_DRIVER_CSE7766 1 +#define ENABLE_DRIVER_HT16K33 1 +#define ENABLE_DRIVER_MAX72XX 1 #define ENABLE_DRIVER_TUYAMCU 1 #define ENABLE_TEST_COMMANDS 1 #define ENABLE_CALENDAR_EVENTS 1 @@ -45,6 +47,9 @@ #define ENABLE_DRIVER_BRIDGE 1 #define ENABLE_HTTPBUTTONS 1 #define ENABLE_ADVANCED_CHANNELTYPES_DISCOVERY 1 +#define ENABLE_DRIVER_WEMO 1 +#define ENABLE_DRIVER_HUE 1 +#define ENABLE_DRIVER_CHARGINGLIMIT 1 #elif PLATFORM_BL602 @@ -54,6 +59,7 @@ #define ENABLE_DRIVER_BL0937 1 #define ENABLE_DRIVER_BL0942 1 #define ENABLE_DRIVER_CSE7766 1 +#define ENABLE_DRIVER_WEMO 1 #elif PLATFORM_BEKEN @@ -65,12 +71,17 @@ #define ENABLE_DRIVER_BL0942SPI 1 #define ENABLE_DRIVER_CSE7766 1 #define ENABLE_DRIVER_TUYAMCU 1 +//#define ENABLE_DRIVER_HT16K33 1 +//#define ENABLE_DRIVER_MAX72XX 1 #define ENABLE_I2C 1 #define ENABLE_TEST_COMMANDS 1 #define ENABLE_CALENDAR_EVENTS 1 #define ENABLE_DRIVER_BRIDGE 1 #define ENABLE_HTTPBUTTONS 1 #define ENABLE_ADVANCED_CHANNELTYPES_DISCOVERY 1 +#define ENABLE_DRIVER_WEMO 1 +#define ENABLE_DRIVER_HUE 1 +#define ENABLE_DRIVER_CHARGINGLIMIT 1 #else diff --git a/src/selftest/selftest_DHT.c b/src/selftest/selftest_DHT.c index d3feb9919..8eac7fea4 100644 --- a/src/selftest/selftest_DHT.c +++ b/src/selftest/selftest_DHT.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_DHT() { // reset whole device diff --git a/src/selftest/selftest_buttonEvents.c b/src/selftest/selftest_buttonEvents.c index 97f06b64a..bd3b31932 100644 --- a/src/selftest/selftest_buttonEvents.c +++ b/src/selftest/selftest_buttonEvents.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_ButtonEvents() { // reset whole device diff --git a/src/selftest/selftest_changeHandlers.c b/src/selftest/selftest_changeHandlers.c index 09f8922ec..8809ab8f5 100644 --- a/src/selftest/selftest_changeHandlers.c +++ b/src/selftest/selftest_changeHandlers.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_ChangeHandlers() { // reset whole device diff --git a/src/selftest/selftest_changeHandlers_mqtt.c b/src/selftest/selftest_changeHandlers_mqtt.c index 87deb0949..15aad3765 100644 --- a/src/selftest/selftest_changeHandlers_mqtt.c +++ b/src/selftest/selftest_changeHandlers_mqtt.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_ChangeHandlers_MQTT() { // reset whole device diff --git a/src/selftest/selftest_chargingDriver.c b/src/selftest/selftest_chargingDriver.c new file mode 100644 index 000000000..114c4c0a6 --- /dev/null +++ b/src/selftest/selftest_chargingDriver.c @@ -0,0 +1,49 @@ +#ifdef WINDOWS + +#include "selftest_local.h" + +void Test_ChargeLimitDriver() { + int i; + // reset whole device + SIM_ClearOBK(0); + + int start10 = 1000; + CHANNEL_Set(10, start10, 0); + CHANNEL_Set(12, 0, 0); + CMD_ExecuteCommand("startDriver ChargingLimit", 0); + // chSetupLimit 5 5000 3600 "POWER OFF" + CMD_ExecuteCommand("alias MyEvent SetChannel 12 1", 0); + CMD_ExecuteCommand("chSetupLimit 10 5 3600 MyEvent", 0); + + // simulate time passing + for (int i = 0; i < 10; i++) { + CMD_ExecuteCommand("addChannel 10 2", 0); + Main_OnEverySecond(); + int val10 = CHANNEL_Get(10); + int nowDelta = val10 - start10; + if (nowDelta >= 5) { + SELFTEST_ASSERT_CHANNEL(12,1); + } + else { + SELFTEST_ASSERT_CHANNEL(12, 0); + } + } + + // simulate time passing - time limit 5 seconds + CHANNEL_Set(12, 0, 0); + CMD_ExecuteCommand("chSetupLimit 10 5 5 MyEvent", 0); + for (int i = 0; i < 15; i++) { + Main_OnEverySecond(); + // has 5 seconds passed? + if (i >= 4) { + SELFTEST_ASSERT_CHANNEL(12, 1); + } + else { + SELFTEST_ASSERT_CHANNEL(12, 0); + } + } + +} + + +#endif diff --git a/src/selftest/selftest_cmd_alias.c b/src/selftest/selftest_cmd_alias.c index 93c131889..6f7b8408f 100644 --- a/src/selftest/selftest_cmd_alias.c +++ b/src/selftest/selftest_cmd_alias.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Commands_Alias() { // reset whole device diff --git a/src/selftest/selftest_cmd_calendar.c b/src/selftest/selftest_cmd_calendar.c index 8e77b9eff..78e0cc8af 100644 --- a/src/selftest/selftest_cmd_calendar.c +++ b/src/selftest/selftest_cmd_calendar.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Commands_Calendar() { // reset whole device diff --git a/src/selftest/selftest_cmd_channels.c b/src/selftest/selftest_cmd_channels.c index 5d9ea2fa2..8a39ac919 100644 --- a/src/selftest/selftest_cmd_channels.c +++ b/src/selftest/selftest_cmd_channels.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Commands_Channels() { // reset whole device @@ -218,6 +218,17 @@ void Test_Commands_Channels() { SELFTEST_ASSERT_CHANNEL(10, 0); } + + // test backlog + CMD_ExecuteCommand("backlog setChannel 1 11; setChannel 2 22; setChannel 3 33;", 0); + SELFTEST_ASSERT_CHANNEL(1, 11); + SELFTEST_ASSERT_CHANNEL(2, 22); + SELFTEST_ASSERT_CHANNEL(3, 33); + CMD_ExecuteCommand("backlog setChannel 1 101 ; setChannel 2 202 ; setChannel 3 303 ;", 0); + SELFTEST_ASSERT_CHANNEL(1, 101); + SELFTEST_ASSERT_CHANNEL(2, 202); + SELFTEST_ASSERT_CHANNEL(3, 303); + } diff --git a/src/selftest/selftest_cmd_generic.c b/src/selftest/selftest_cmd_generic.c index ada420e43..e38ba6530 100644 --- a/src/selftest/selftest_cmd_generic.c +++ b/src/selftest/selftest_cmd_generic.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Commands_Generic() { // reset whole device diff --git a/src/selftest/selftest_cmd_startup.c b/src/selftest/selftest_cmd_startup.c index 0ef5f0845..d6164aceb 100644 --- a/src/selftest/selftest_cmd_startup.c +++ b/src/selftest/selftest_cmd_startup.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Commands_Startup() { // reset whole device diff --git a/src/selftest/selftest_demo_exclusiveRelays.c b/src/selftest/selftest_demo_exclusiveRelays.c index 7877fa675..392c64786 100644 --- a/src/selftest/selftest_demo_exclusiveRelays.c +++ b/src/selftest/selftest_demo_exclusiveRelays.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" diff --git a/src/selftest/selftest_demo_mapFanSpeedToRelays.c b/src/selftest/selftest_demo_mapFanSpeedToRelays.c index f993f4a4d..d267f0752 100644 --- a/src/selftest/selftest_demo_mapFanSpeedToRelays.c +++ b/src/selftest/selftest_demo_mapFanSpeedToRelays.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" diff --git a/src/selftest/selftest_expandConstant.c b/src/selftest/selftest_expandConstant.c index 1a0f8e09e..5290ff84f 100644 --- a/src/selftest/selftest_expandConstant.c +++ b/src/selftest/selftest_expandConstant.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_ExpandConstant() { char buffer[512]; @@ -114,6 +114,29 @@ void Test_ExpandConstant() { SELFTEST_ASSERT_STRING(ptr, "456+2022"); free(ptr); //system("pause"); + + + CFG_SetFlag(OBK_FLAG_HTTP_PINMONITOR, 0); + ptr = CMD_ExpandingStrdup("$FLAG13"); + SELFTEST_ASSERT_STRING(ptr, "0"); + free(ptr); + + CFG_SetFlag(OBK_FLAG_HTTP_PINMONITOR, 1); + ptr = CMD_ExpandingStrdup("$FLAG13"); + SELFTEST_ASSERT_STRING(ptr, "1"); + free(ptr); + + CFG_SetFlag(OBK_FLAG_HTTP_PINMONITOR, 0); + ptr = CMD_ExpandingStrdup("$FLAG13"); + SELFTEST_ASSERT_STRING(ptr, "0"); + free(ptr); + + CFG_SetFlag(OBK_FLAG_HTTP_PINMONITOR, 1); + ptr = CMD_ExpandingStrdup("$FLAG13"); + SELFTEST_ASSERT_STRING(ptr, "1"); + free(ptr); + + CFG_SetFlag(OBK_FLAG_HTTP_PINMONITOR, 0); } #endif diff --git a/src/selftest/selftest_expressions.c b/src/selftest/selftest_expressions.c index a456d9a81..3513267ea 100644 --- a/src/selftest/selftest_expressions.c +++ b/src/selftest/selftest_expressions.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Expressions_RunTests_Basic() { // reset whole device diff --git a/src/selftest/selftest_flags.c b/src/selftest/selftest_flags.c index c91f1eca0..e5276ae8e 100644 --- a/src/selftest/selftest_flags.c +++ b/src/selftest/selftest_flags.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Flags() { // reset whole device diff --git a/src/selftest/selftest_hass_discovery.c b/src/selftest/selftest_hass_discovery.c index 3e171f7f7..0238d3cea 100644 --- a/src/selftest/selftest_hass_discovery.c +++ b/src/selftest/selftest_hass_discovery.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_HassDiscovery_Relay_1x() { const char *shortName = "WinRelTest1x"; diff --git a/src/selftest/selftest_hass_discovery_ext.c b/src/selftest/selftest_hass_discovery_ext.c index 4f949402b..cb115c3f3 100644 --- a/src/selftest/selftest_hass_discovery_ext.c +++ b/src/selftest/selftest_hass_discovery_ext.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_HassDiscovery_TuyaMCU_VoltageCurrentPower() { const char *shortName = "WinTuyatest"; diff --git a/src/selftest/selftest_http_client.c b/src/selftest/selftest_http_client.c index 7cb2b9438..a3938a6b2 100644 --- a/src/selftest/selftest_http_client.c +++ b/src/selftest/selftest_http_client.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_HTTP_Client() { // reset whole device diff --git a/src/selftest/selftest_if.c b/src/selftest/selftest_if.c index 564b33b2a..ecc734611 100644 --- a/src/selftest/selftest_if.c +++ b/src/selftest/selftest_if.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Command_If() { // reset whole device diff --git a/src/selftest/selftest_if_inside_backlog.c b/src/selftest/selftest_if_inside_backlog.c index 431336ead..b54fa116f 100644 --- a/src/selftest/selftest_if_inside_backlog.c +++ b/src/selftest/selftest_if_inside_backlog.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_IF_Inside_Backlog() { // reset whole device diff --git a/src/selftest/selftest_led.c b/src/selftest/selftest_led.c index 0915db490..5be13f4ea 100644 --- a/src/selftest/selftest_led.c +++ b/src/selftest/selftest_led.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_LEDDriver_CW() { int i; diff --git a/src/selftest/selftest_lfs.c b/src/selftest/selftest_lfs.c index cf33fa59c..9cd110da0 100644 --- a/src/selftest/selftest_lfs.c +++ b/src/selftest/selftest_lfs.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_LFS() { char buffer[64]; diff --git a/src/selftest/selftest_local.h b/src/selftest/selftest_local.h index e99f11751..b0e10a4d2 100644 --- a/src/selftest/selftest_local.h +++ b/src/selftest/selftest_local.h @@ -113,6 +113,7 @@ void Test_WaitFor(); void Test_IF_Inside_Backlog(); void Test_MQTT_Get_LED_EnableAll(); void Test_TuyaMCU_BatteryPowered(); +void Test_ChargeLimitDriver(); void Test_GetJSONValue_Setup(const char *text); void Test_FakeHTTPClientPacket_GET(const char *tg); diff --git a/src/selftest/selftest_mapRanges.c b/src/selftest/selftest_mapRanges.c index 97a48d56e..82709dfac 100644 --- a/src/selftest/selftest_mapRanges.c +++ b/src/selftest/selftest_mapRanges.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_MapRanges() { char buffer[64]; diff --git a/src/selftest/selftest_multiplePinsOnChannel.c b/src/selftest/selftest_multiplePinsOnChannel.c index d1350654a..038fdffbe 100644 --- a/src/selftest/selftest_multiplePinsOnChannel.c +++ b/src/selftest/selftest_multiplePinsOnChannel.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" static int PIN_BUTTON = 10; static int PIN_LED_n = 11; diff --git a/src/selftest/selftest_ntp.c b/src/selftest/selftest_ntp.c index 690b112c7..118ccc595 100644 --- a/src/selftest/selftest_ntp.c +++ b/src/selftest/selftest_ntp.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_NTP() { // reset whole device diff --git a/src/selftest/selftest_repeatingEvents.c b/src/selftest/selftest_repeatingEvents.c index d5d2ae473..c4e41bd56 100644 --- a/src/selftest/selftest_repeatingEvents.c +++ b/src/selftest/selftest_repeatingEvents.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_RepeatingEvents() { // reset whole device diff --git a/src/selftest/selftest_role_toggleAll.c b/src/selftest/selftest_role_toggleAll.c index 3133e9e37..8525f7b6d 100644 --- a/src/selftest/selftest_role_toggleAll.c +++ b/src/selftest/selftest_role_toggleAll.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Role_ToggleAll() { // reset whole device diff --git a/src/selftest/selftest_role_toggleAll_2.c b/src/selftest/selftest_role_toggleAll_2.c index e21281c5e..28569fdda 100644 --- a/src/selftest/selftest_role_toggleAll_2.c +++ b/src/selftest/selftest_role_toggleAll_2.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Role_ToggleAll_2() { // reset whole device diff --git a/src/selftest/selftest_script.c b/src/selftest/selftest_script.c index 94ccc346d..b7eeed664 100644 --- a/src/selftest/selftest_script.c +++ b/src/selftest/selftest_script.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" const char *demo_loop_1 = "setChannel 10 0\r\n" diff --git a/src/selftest/selftest_tasmota.c b/src/selftest/selftest_tasmota.c index 2a5818009..fc3619897 100644 --- a/src/selftest/selftest_tasmota.c +++ b/src/selftest/selftest_tasmota.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Tasmota_MQTT_Switch() { SIM_ClearOBK(0); diff --git a/src/selftest/selftest_tokenizer.c b/src/selftest/selftest_tokenizer.c index 5f9d71133..fd8fc7ba7 100644 --- a/src/selftest/selftest_tokenizer.c +++ b/src/selftest/selftest_tokenizer.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_Tokenizer() { // reset whole device diff --git a/src/selftest/selftest_tuyaMCU.c b/src/selftest/selftest_tuyaMCU.c index 1d4db8866..2bb2dd8cd 100644 --- a/src/selftest/selftest_tuyaMCU.c +++ b/src/selftest/selftest_tuyaMCU.c @@ -1,12 +1,14 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" void Test_TuyaMCU_Basic() { // reset whole device SIM_ClearOBK(0); + SIM_UART_InitReceiveRingBuffer(2048); + CMD_ExecuteCommand("startDriver TuyaMCU", 0); // This will map TuyaMCU fnID 2 of type Value to channel 15 @@ -40,6 +42,97 @@ void Test_TuyaMCU_Basic() { // Now, channel 15 should be set to 120... SELFTEST_ASSERT_CHANNEL(15, 120); + SIM_ClearUART(); + + // + // check sending from OBK to MCU + // + // OBK sends: + // 55 AA 00 06 00 05 1001000100 1C + //HEADER VER = 00 SetDP LEN fnId = 16 Bool V = 0 CHK + CMD_ExecuteCommand("tuyaMcu_sendState 16 1 0", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 05 1001000100 1C"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + // OBK sends: + // 55 AA 00 06 00 05 0101000101 0E + // HEADER VER = 00 Unk LEN fnId = 1 Bool V = 1 CHK + CMD_ExecuteCommand("tuyaMcu_sendState 1 1 1", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 05 0101000101 0E"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + // OBK sends: + // 55 AA 00 06 00 05 0101000100 0D + // HEADER VER = 00 Unk LEN fnId = 1 Bool V = 0 CHK + CMD_ExecuteCommand("tuyaMcu_sendState 1 1 0", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 05 0101000100 0D"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + + // OBK sends: + // 55 AA 00 06 00 05 6C01000101 79 + // HEADER VER = 00 Unk LEN fnId = 108 Bool V = 1 CHK + CMD_ExecuteCommand("tuyaMcu_sendState 108 1 1", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 05 6C01000101 79"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + + + // OBK sends: + // 55 AA 00 06 00 05 6D04000110 8C + // HEADER VER = 00 Unk LEN fnId = 109 Enum V = 16 CHK + CMD_ExecuteCommand("tuyaMcu_sendState 109 4 16", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 05 6D04000110 8C"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + + + + + + + // OBK sends: + // 55 AA 00 06 00 14 1100001001010050030100F5040100A008000032 64 + //HEADER VER = 00 Unk LEN fnId = 17 Raw V = 01 01 00 50 03 01 00 F5 04 01 00 A0 08 00 00 32 CHK + CMD_ExecuteCommand("tuyaMcu_sendState 17 0 01010050030100F5040100A008000032", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 14 1100001001010050030100F5040100A008000032 64"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + // check channel as argument in raw + CMD_ExecuteCommand("setChannel 10 1",0); + CMD_ExecuteCommand("tuyaMcu_sendState 17 0 $CH10$$CH10$0050030100F5040100A008000032", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 14 1100001001010050030100F5040100A008000032 64"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + // check channel as argument in raw + CMD_ExecuteCommand("setChannel 10 1", 0); + CMD_ExecuteCommand("setChannel 11 0", 0); + CMD_ExecuteCommand("setChannel 2 0x50", 0); + CMD_ExecuteCommand("setChannel 3 0x03", 0); + CMD_ExecuteCommand("setChannel 4 0xF5", 0); + CMD_ExecuteCommand("tuyaMcu_sendState 17 0 $CH10$$CH10$$CH11$$CH2$$CH3$0100$CH4$040100A008000032", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 14 1100001001010050030100F5040100A008000032 64"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + + // check channel as argument in raw + CMD_ExecuteCommand("setChannel 10 1", 0); + CMD_ExecuteCommand("setChannel 11 0", 0); + CMD_ExecuteCommand("setChannel 2 0x50", 0); + CMD_ExecuteCommand("setChannel 3 0x03", 0); + CMD_ExecuteCommand("setChannel 4 0xF5", 0); + CMD_ExecuteCommand("tuyaMcu_sendState 17 0 $CH10$ $CH10$ $CH11$ $CH2$ $CH3$ 01 00 $CH4$ 04 01 00 A0 08 00 00 32", 0); + SELFTEST_ASSERT_HAS_SENT_UART_STRING("55 AA 00 06 00 14 1100001001010050030100F5040100A008000032 64"); + // nothing is sent by OBK at that point + SELFTEST_ASSERT_HAS_UART_EMPTY(); + // cause error //SELFTEST_ASSERT_CHANNEL(15, 666); } diff --git a/src/selftest/selftest_twoPWMsOneChannel.c b/src/selftest/selftest_twoPWMsOneChannel.c index b7227ac84..2dccea61b 100644 --- a/src/selftest/selftest_twoPWMsOneChannel.c +++ b/src/selftest/selftest_twoPWMsOneChannel.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" // This will allow us to treat multiple PWMs on a single channel as one PWM channel. // Thanks to this users can turn for example RGB LED controller diff --git a/src/selftest/selftest_util_mqtt_json.c b/src/selftest/selftest_util_mqtt_json.c index 509d1cc31..a4a7a5c77 100644 --- a/src/selftest/selftest_util_mqtt_json.c +++ b/src/selftest/selftest_util_mqtt_json.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" bool SIM_BeginParsingMQTTJSON(const char *topic, bool bPrefixMode) { const char *data; diff --git a/src/selftest/selftest_waitFor.c b/src/selftest/selftest_waitFor.c index d33642d9b..a8d1f6af9 100644 --- a/src/selftest/selftest_waitFor.c +++ b/src/selftest/selftest_waitFor.c @@ -1,6 +1,6 @@ #ifdef WINDOWS -#include "selftest_local.h". +#include "selftest_local.h" /* Example autoexec.bat usage - wait for MQTT connect on startup: diff --git a/src/sim/WinMenuBar.cpp b/src/sim/WinMenuBar.cpp index 3cbefe88e..a6dcffe6e 100644 --- a/src/sim/WinMenuBar.cpp +++ b/src/sim/WinMenuBar.cpp @@ -6,7 +6,28 @@ #include "Shape.h" #include "PrefabManager.h" #include + +#if DEBUG #pragma comment (lib, "nfd_d.lib") +#else +#pragma comment (lib, "nfd.lib") +#pragma comment (lib, "vcruntime.lib") +char *strncat(char *s1, const char *s2, size_t n) +{ + unsigned int len1 = strlen(s1); + unsigned int len2 = strlen(s2); + + if (len2 < n) { + strcpy(&s1[len1], s2); + } + else { + strncpy(&s1[len1], s2, n); + s1[len1 + n] = '\0'; + } + return s1; +} + +#endif CWinMenuBar::CWinMenuBar() { diff --git a/src/sim/sim_uart.c b/src/sim/sim_uart.c index 4c6c1c196..7e9e0dae8 100644 --- a/src/sim/sim_uart.c +++ b/src/sim/sim_uart.c @@ -45,7 +45,8 @@ void SIM_AppendUARTByte(byte rc) { bool SIM_UART_ExpectAndConsumeHByte(byte b) { byte nextB; - if (SIM_UART_GetDataSize() == 0) + int dataSize = SIM_UART_GetDataSize(); + if (dataSize == 0) return false; nextB = SIM_UART_GetByte(0); if (nextB == b) { diff --git a/src/user_main.c b/src/user_main.c index dcc72f493..b0db811db 100644 --- a/src/user_main.c +++ b/src/user_main.c @@ -917,6 +917,9 @@ void Main_Init_BeforeDelay_Unsafe(bool bAutoRunScripts) { // so ALL commands expected in autoexec.bat should have been registered by now... // but DON't run autoexec if we have had 2+ boot failures CMD_Init_Early(); +#if WINDOWS + CMD_InitSimulatorOnlyCommands(); +#endif /* Automatic disable of PIN MONITOR after reboot */ if (CFG_HasFlag(OBK_FLAG_HTTP_PINMONITOR)) { @@ -948,6 +951,11 @@ void Main_Init_BeforeDelay_Unsafe(bool bAutoRunScripts) { if (PIN_FindPinIndexForRole(IOR_BP1658CJ_CLK, -1) != -1 && PIN_FindPinIndexForRole(IOR_BP1658CJ_DAT, -1) != -1) { #ifndef OBK_DISABLE_ALL_DRIVERS DRV_StartDriver("BP1658CJ"); +#endif + } + if (PIN_FindPinIndexForRole(IOR_KP18058_CLK, -1) != -1 && PIN_FindPinIndexForRole(IOR_KP18058_DAT, -1) != -1) { +#ifndef OBK_DISABLE_ALL_DRIVERS + DRV_StartDriver("KP18058"); #endif } if (PIN_FindPinIndexForRole(IOR_BL0937_CF, -1) != -1 && PIN_FindPinIndexForRole(IOR_BL0937_CF1, -1) != -1 diff --git a/src/win_main.c b/src/win_main.c index 3fe10048e..04e4ce7d6 100644 --- a/src/win_main.c +++ b/src/win_main.c @@ -28,7 +28,7 @@ int accum_time = 0; int win_frameNum = 0; // this time counter is simulated, I need this for unit tests to work int g_simulatedTimeNow = 0; -extern int g_port; +extern int g_httpPort; #define DEFAULT_FRAME_TIME 5 @@ -128,6 +128,9 @@ void SIM_ClearOBK(const char *flashPath) { } void Win_DoUnitTests() { + Test_ChargeLimitDriver(); + // this is slowest + Test_TuyaMCU_Basic(); Test_Battery(); Test_TuyaMCU_BatteryPowered(); Test_JSON_Lib(); @@ -177,8 +180,6 @@ void Win_DoUnitTests() { Test_Http(); Test_DeviceGroups(); - // this is slowest - Test_TuyaMCU_Basic(); @@ -230,7 +231,7 @@ int __cdecl main(int argc, char **argv) i++; if (i < argc && sscanf(argv[i], "%d", &value) == 1) { - g_port = value; + g_httpPort = value; } } else if (wal_strnicmp(argv[i] + 1, "w", 1) == 0) { i++;