From 0924d7a2e682681b8f712c23c1cf74480aca02b9 Mon Sep 17 00:00:00 2001 From: Staars Date: Wed, 21 Nov 2018 19:13:52 +0100 Subject: [PATCH 01/20] first integration of the driver into the TASMOTA-repo --- sonoff/language/en-GB.h | 2 + sonoff/my_user_config.h | 1 + sonoff/sonoff_template.h | 11 +- sonoff/xsns_36_mgc3130.ino | 651 +++++++++++++++++++++++++++++++++++++ 4 files changed, 663 insertions(+), 2 deletions(-) create mode 100644 sonoff/xsns_36_mgc3130.ino diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index 1a9304a7d..c276187ab 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 86384fdbc..e1cf92cd3 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -299,6 +299,7 @@ // #define USE_SI1145 // Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code) #define USE_LM75AD // Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code) // #define USE_APDS9960 // Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code) + #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) // #define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index dcc87c27f..3135dd339 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -133,6 +133,8 @@ enum UserSelectablePins { GPIO_RFRECV, // RF receiver GPIO_TUYA_TX, // Tuya Serial interface GPIO_TUYA_RX, // Tuya Serial interface + GPIO_MGC3130_XFER, // MGC3130 Transfer + GPIO_MGC3130_RESET, // MGC3130 Reset GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -190,7 +192,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|" D_SENSOR_TX20_TX "|" D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|" - D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX; + D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|" + D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET; /********************************************************************************************/ @@ -426,7 +429,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { #endif #ifdef USE_TUYA_DIMMER GPIO_TUYA_TX, // Tuya Serial interface - GPIO_TUYA_RX // Tuya Serial interface + GPIO_TUYA_RX, // Tuya Serial interface +#endif +#ifdef USE_MGC3130 + GPIO_MGC3130_XFER, + GPIO_MGC3130_RESET #endif }; diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino new file mode 100644 index 000000000..05662379c --- /dev/null +++ b/sonoff/xsns_36_mgc3130.ino @@ -0,0 +1,651 @@ +/* + xsns_91_MGC3130.ino - Support for I2C MGC3130 Electric Field Sensor for Sonoff-Tasmota + + Copyright (C) 2018 Christian Baars & Theo Arends + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +//#define USE_MGC3130 + +#ifdef USE_I2C +#ifdef USE_MGC3130 + +#define XSNS_36 36 + +/*********************************************************************************************\ + * MGC3130 - Electric Field Sensor + * + * Adaption for TASMOTA: Christian Baars + * based on various implementations from Pimoroni, jspark311, hoverlabs and scjurgen + * + * I2C Address: 0x42 + * + * Wiring: SDA/SCL as usual plus RESET and TRANSFER -> 4 Wires +\*********************************************************************************************/ + +#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** + +#define MGC3130_I2C_ADDR 0x42 + +#define MGC3130_xfer pin[GPIO_MGC3130_XFER] +#define MGC3130_reset pin[GPIO_MGC3130_RESET] + + +bool MGC3130_type = false; +char MGC3130stype[8]; + + +#define MGC3130_SYSTEM_STATUS 0x15 +#define MGC3130_REQUEST_MSG 0x06 +#define MGC3130_FW_VERSION 0x83 +#define MGC3130_SET_RUNTIME 0xA2 +#define MGC3130_SENSOR_DATA 0x91 + + +#define MGC3130_GESTURE_GARBAGE 1 +#define MGC3130_FLICK_WEST_EAST 2 +#define MGC3130_FLICK_EAST_WEST 3 +#define MGC3130_FLICK_SOUTH_NORTH 4 +#define MGC3130_FLICK_NORTH_SOUTH 5 +#define MGC3130_CIRCLE_CLOCKWISE 6 //not active in airwheel mode +#define MGC3130_CIRCLE_CCLOCKWISE 7 //not active in airwheel mode + +#define MGC3130_MIN_ROTVALUE 0 +#define MGC3130_MAX_ROTVALUE 1023 +#define MGC3130_MIN_ZVALUE 32768 // if we fly under the radar, we do not report anything + + +#ifdef USE_WEBSERVER +const char HTTP_MGC_3130_SNS[] PROGMEM = "%s" + "{s}" "%s" "{m}%s{e}" + "{s}" "HwRev" "{m}%u.%u{e}" + "{s}" "loaderVer" "{m}%u.%u{e}" + "{s}" "platVer" "{m}%u{e}"; // {s} = , {m} = , {e} = +#endif // USE_WEBSERVER + + +/*********************************************************************************************\ + * MGC3130 + * + * Programmer : MGC3130 Datasheet +\*********************************************************************************************/ +#pragma pack(1) +union MGC3130_Union{ + uint8_t buffer[132]; + struct + { + // header + uint8_t msgSize; // in Bytes + uint8_t flag; //not used + uint8_t counter; // cyclic counter of transmitted messages + uint8_t id; // 0x91 for data output + // payload + struct { + uint8_t DSPStatus:1; + uint8_t gestureInfo:1; + uint8_t touchInfo:1; + uint8_t airWheelInfo:1; + uint8_t xyzPosition:1; + uint8_t noisePower:1; + uint8_t reserved:2; + uint8_t electrodeConfiguration:3; + uint8_t CICData:1; + uint8_t SDData:1; + uint16_t reserved2:3; + } outputConfigMask; + uint8_t timestamp; + struct { + uint8_t positionValid:1; + uint8_t airWheelValid:1; + uint8_t rawDataValid:1; + uint8_t noisePowerValid:1; + uint8_t environmentalNoise:1; + uint8_t clipping:1; + uint8_t reserved:1; + uint8_t DSPRunning:1; + } systemInfo; + uint16_t dspInfo; + struct { + uint8_t gestureCode:8; // 0 -> No Gesture + uint8_t reserved:4; + uint8_t gestureType:4; //garbage, flick or circular + uint8_t edgeFlick:1; + uint16_t reserved2:14; + uint8_t gestureInProgress:1; // If "1" Gesture recognition in progress + } gestureInfo; + struct { + uint8_t touchSouth:1; + uint8_t touchWest:1; //:Bit 01 + uint8_t touchNorth:1; //:Bit 02 + uint8_t touchEast:1; //:Bit 03 + uint8_t touchCentre:1; //:Bit 04 + uint8_t tapSouth:1; //:Bit 05 + uint8_t tapWest:1; //:Bit 06 + uint8_t tapNorth:1; //:Bit 07 + uint8_t tapEast :1; //:Bit 08 + uint8_t tapCentre:1; //:Bit 09 + uint8_t doubleTapSouth:1; //:Bit 10 + uint8_t doubleTapWest:1; //:Bit 11 + uint8_t doubleTapNorth:1; //:Bit 12 + uint8_t doubleTapEast:1; //:Bit 13 + uint8_t doubleTapCentre:1; //:Bit 14 + uint8_t reserved:1; //:Bit 15 + uint8_t touchCounter; //period between the time when the hand starts moving to touch until it is detected + uint8_t reserved2; + } touchInfo; + int8_t airWheel; + uint8_t reserved; + uint16_t x; + uint16_t y; + uint16_t z; + float noisePower; + float CICData[4]; // uncalibrated sensor data + float SDData[4]; // signal deviation + } out; + struct { + uint8_t header[3]; + // payload + uint8_t valid; + uint8_t hwRev[2]; + uint8_t parameterStartAddr; + uint8_t loaderVersion[2]; + uint8_t loaderPlatform; + uint8_t fwStartAddr; + char fwVersion[120]; + } fw; + struct{ + uint8_t id; + uint8_t size; + uint16_t error; + uint32_t reserved; + uint32_t reserved1; + } status; +} MGC_data; +#pragma pack() + +char MGC3130_currentGesture[12]; + +int8_t MGC3130_delta, MGC3130_lastrotation = 0; +int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0; + +uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0; + +uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0; +char MGC3130_firmwareInfo[20]; + +uint8_t MGC3130_touchTimeout = 0; +uint16_t MGC3130_touchCounter = 1; // measure how long you touch the surface in loop cycles +uint32_t MGC3130_touchTimeStamp = millis(); +bool MGC3130_triggeredByTouch = false; + +uint8_t MGC3130_mode = 1; // 1-gesture; 2-airwheel; 3-position + + +// predefined messages +uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; +uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; +uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; + +void MGC3130_triggerTele(){ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + #ifdef USE_RULES + RulesTeleperiod(); // Allow rule based HA messages + #endif // USE_RULES + } +} + +void MGC3130_handleSensorData(){ + if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ + if (MGC3130_handleTouch()){ + MGC3130_triggeredByTouch = true; + MGC3130_triggerTele(); + } + } + + if(MGC3130_mode == 1){ + if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ + MGC3130_handleGesture(); + MGC3130_triggerTele(); + } + } + if(MGC3130_mode == 2){ + if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ + MGC3130_handleAirWheel(); + MGC3130_triggerTele(); + } + } + if(MGC3130_mode == 3){ + if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ + MGC3130_triggerTele(); + } + } +} + +void MGC3130_sendMessage(uint8_t data[], uint8_t length){ + Wire.beginTransmission(MGC3130_I2C_ADDR); + Wire.write(data,length); + Wire.endTransmission(); + delay(2); + MGC3130_receiveMessage(); +} + + +void MGC3130_handleGesture(){ + //char log[LOGSZ]; + char edge[5]; + if (MGC_data.out.gestureInfo.edgeFlick){ + snprintf_P(edge, sizeof(edge), PSTR("ED_")); + } + else{ + snprintf_P(edge, sizeof(edge), PSTR("")); + } + switch(MGC_data.out.gestureInfo.gestureCode){ + case MGC3130_GESTURE_GARBAGE: + //snprintf_P(log, sizeof(log), PSTR("NONE")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE")); + break; + case MGC3130_FLICK_WEST_EAST: + //snprintf_P(log, sizeof(log), PSTR("%sFL_WE"), edge); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge); + break; + case MGC3130_FLICK_EAST_WEST: + //snprintf_P(log, sizeof(log), PSTR("%sFL_EW"), edge); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge); + break; + case MGC3130_FLICK_SOUTH_NORTH: + //snprintf_P(log, sizeof(log), PSTR("%sFL_SN"), edge); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge); + break; + case MGC3130_FLICK_NORTH_SOUTH: + //snprintf_P(log, sizeof(log), PSTR("%sFL_NS"), edge); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge); + break; + case MGC3130_CIRCLE_CLOCKWISE: + //snprintf_P(log, sizeof(log), PSTR("CW")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW")); + break; + case MGC3130_CIRCLE_CCLOCKWISE: + //snprintf_P(log, sizeof(log), PSTR("CCW")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW")); + break; + } + //AddLog_P(LOG_LEVEL_DEBUG, log); +} + +bool MGC3130_handleTouch(){ + //char log[LOGSZ]; + bool success = false; // if we find a touch of higher order, we are done + if (MGC_data.out.touchInfo.doubleTapCentre && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_CENTRE")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapEast && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_EAST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapNorth && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_NORTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapWest && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_WEST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapSouth && !success){ + //snprintf_P(log, sizeof(log), PSTR("DTAP_SOUTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + if (MGC_data.out.touchInfo.tapCentre && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_CENTRE")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapEast && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_EAST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapNorth && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_NORTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapWest && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_WEST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapSouth && !success){ + //snprintf_P(log, sizeof(log), PSTR("TAP_SOUTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.touchCentre && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_CENTRE")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C")); + success = true; + MGC3130_touchCounter++; // This will reset to 0 after touching for approx. 1h and 50 minutes ;) + } + else if (MGC_data.out.touchInfo.touchEast && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_EAST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchNorth && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_NORTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchWest && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_WEST")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchSouth && !success){ + //snprintf_P(log, sizeof(log), PSTR("TOUCH_SOUTH")); + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S")); + success = true; + MGC3130_touchCounter++; + } + //AddLog_P(LOG_LEVEL_DEBUG, log); + return success; +} + +void MGC3130_handleAirWheel(){ + MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation; + MGC3130_lastrotation = MGC_data.out.airWheel; + + MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta; + if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){ + MGC3130_rotValue = MGC3130_MIN_ROTVALUE; + } + if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){ + MGC3130_rotValue = MGC3130_MAX_ROTVALUE; + } +} + +void MGC3130_handleSystemStatus(){ + //Serial.println("Got System status"); +} + +bool MGC3130_receiveMessage(){ + if(MGC3130_readData()){ + switch(MGC_data.out.id){ + case MGC3130_SENSOR_DATA: + MGC3130_handleSensorData(); + break; + case MGC3130_SYSTEM_STATUS: + MGC3130_handleSystemStatus(); + break; + case MGC3130_FW_VERSION: + hwRev[0] = MGC_data.fw.hwRev[1]; + hwRev[1] = MGC_data.fw.hwRev[0]; + loaderVersion[0] = MGC_data.fw.loaderVersion[0]; + loaderVersion[1] = MGC_data.fw.loaderVersion[1]; + loaderPlatform = MGC_data.fw.loaderPlatform; + snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion); + MGC3130_firmwareInfo[20] = '\0'; + // Serial.print(MGC3130_firmwareInfo); + break; + } + return true; + } + return false; +} + +bool MGC3130_readData() +{ + bool success = false; + if (!digitalRead(MGC3130_xfer)){ + pinMode(MGC3130_xfer, OUTPUT); + digitalWrite(MGC3130_xfer, LOW); + Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); // request usual data output + + MGC_data.buffer[0] = 4; // read at least header, but update after first read anyway + unsigned char i = 0; + while(Wire.available() && (i < MGC_data.buffer[0])){ + MGC_data.buffer[i] = Wire.read(); + i++; + } + digitalWrite(MGC3130_xfer, HIGH); + pinMode(MGC3130_xfer, INPUT); + success = true; + } + return success; +} + +void MGC3130_nextMode(){ + if (MGC3130_mode < 3){ + MGC3130_mode++; + } + else{ + MGC3130_mode = 1; + } + switch(MGC3130_mode){ // there is more to be done in the future + case 1: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } +} + +void MGC3130_loop() +{ + if(MGC3130_touchTimeout > 0){ + MGC3130_touchTimeout--; + } + MGC3130_receiveMessage(); +} + + +bool MGC3130_detect(void) +{ + if (MGC3130_type){ + return true; + } + + pinMode(MGC3130_xfer, INPUT_PULLUP); + pinMode(MGC3130_reset, OUTPUT); + digitalWrite(MGC3130_reset, LOW); + delay(10); + digitalWrite(MGC3130_reset, HIGH); + delay(50); + + boolean success = false; + success = MGC3130_receiveMessage(); // This should read the firmware info + if (success) { + strcpy_P(MGC3130stype, PSTR("MGC3130")); + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, MGC3130stype, MGC3130_I2C_ADDR); + AddLog(LOG_LEVEL_DEBUG); + MGC3130_currentGesture[0] = '\0'; + MGC3130_type = true; + } else { + snprintf_P(log_data, sizeof(log_data), PSTR("MGC3130 did not respond at address 0x%x"), MGC3130_I2C_ADDR); + AddLog(LOG_LEVEL_DEBUG); + } + return success; +} + +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ + +void MGC3130_show(boolean json) +{ + if (!MGC3130_type) { + return; + } + + char status_chr[2]; + if(MGC_data.out.systemInfo.DSPRunning){ + sprintf (status_chr, "1"); + } + else{ + sprintf (status_chr, "0"); + } + + + if (json) { + if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) + { + if(MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)){ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), + mqtt_data, MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); + MGC3130_lastSentX = MGC_data.out.x; + MGC3130_lastSentY = MGC_data.out.y; + MGC3130_lastSentZ = MGC_data.out.z; + } + } + MGC3130_triggeredByTouch = false; + + if (MGC3130_mode == 2){ + if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)){ + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"AW\":%i}"), mqtt_data, MGC3130stype, MGC3130_rotValue); + MGC3130_lastSentRotValue = MGC3130_rotValue; + } + } + + if (MGC3130_currentGesture[0] != '\0'){ + if (millis() - MGC3130_touchTimeStamp > 220 ){ + MGC3130_touchCounter = 1; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":%u}"), mqtt_data, MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); + MGC3130_currentGesture[0] = '\0'; + MGC3130_touchTimeStamp = millis(); + } + } +#ifdef USE_WEBSERVER + else { + if (true){ + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGC_3130_SNS, mqtt_data, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); + } +#endif // USE_WEBSERVER +} +} +/*********************************************************************************************\ + * Command Sensor91 + * + * Command | Payload | Description + * ---------|---------|-------------------------- + * Sensor91 | | ... + * Sensor91 | 0 | Next Mode - cycle through the modes + * Sensor91 | 1 | Gesture Mode + * Sensor91 | 2 | Airwheel Mode + * Sensor91 | 3 | Position Mode with x,y,z - z must be higher than half of the max. sensing height +\*********************************************************************************************/ + +bool MGC3130CommandSensor() +{ + boolean serviced = true; + + switch (XdrvMailbox.payload) { + case 0: // cycle through the modes + MGC3130_nextMode(); + break; + case 1: // gesture & touch + MGC3130_mode = 1; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: // airwheel & touch + MGC3130_mode = 2; + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: // position & touch + MGC3130_mode = 3; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +boolean Xsns36(byte function) +{ + boolean result = false; + + if (i2c_flg) { + if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { + MGC3130_detect(); + } else if (MGC3130_type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + MGC3130_loop(); + break; + case FUNC_COMMAND: + if (XSNS_36 == XdrvMailbox.index) { + result = MGC3130CommandSensor(); + } + break; + case FUNC_JSON_APPEND: + MGC3130_show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + MGC3130_show(0); + break; +#endif // USE_WEBSERVER + } + } + } + return result; +} +#endif // USE_MGC3130 +#endif // USE_I2C \ No newline at end of file From 855cc53d93c25ab8f1b953c685a292409602ce56 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 20:51:15 +0100 Subject: [PATCH 02/20] Disable MGC3130 by default --- sonoff/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e1cf92cd3..d70a5b013 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -299,7 +299,7 @@ // #define USE_SI1145 // Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code) #define USE_LM75AD // Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code) // #define USE_APDS9960 // Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code) - #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) +// #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) // #define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) // #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code) From f4115c17fd87d08c00b0e6ed492419804dc616b6 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 20:59:08 +0100 Subject: [PATCH 03/20] Language key for MGC3130 --- sonoff/language/bg-BG.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 1503884c3..3663dfbae 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 039e228cfecfd51ec7c2deec294041476e6a8457 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 20:59:44 +0100 Subject: [PATCH 04/20] Language keys for MGC3130 --- sonoff/language/cs-CZ.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 2b667cec1..e545ec0a9 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 9bf5b17351e6c70c082346bea57eb67eb815a2f9 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:01:09 +0100 Subject: [PATCH 05/20] Language keys for MGC3130 --- sonoff/language/de-DE.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index f0f9e0f17..17acd9194 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 16e65c15417662ee6f99ac961d80a6aa62197d64 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:01:50 +0100 Subject: [PATCH 06/20] Language keys for MGC3130 --- sonoff/language/el-GR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 79558615d..9287d6961 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -530,6 +530,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 4af915ff566a280a2146c8858e39b2df7d22c1a7 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:02:39 +0100 Subject: [PATCH 07/20] Language keys for MGC3130 --- sonoff/language/es-AR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index e5c3135fe..77d835604 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From c5223b5af845ef4dd1e465af9a88e71bc9971e55 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:03:16 +0100 Subject: [PATCH 08/20] Language keys for MGC3130 --- sonoff/language/fr-FR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0dfb2929c..6947bfc54 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 70188e0aebf1793291388d3d611c7ad7d9b2f0ac Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:03:41 +0100 Subject: [PATCH 09/20] Language keys for MGC3130 --- sonoff/language/he-HE.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index cb041ffba..e6ef65a08 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 65c848e4a25339bf954054465a1fe9e08c31bcc8 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:04:15 +0100 Subject: [PATCH 10/20] Language keys for MGC3130 --- sonoff/language/hu-HU.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 5cee46a52..81e4e7756 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 1961e5b9d9ef19cea5704a23dd569ee6447a697c Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:04:41 +0100 Subject: [PATCH 11/20] Language keys for MGC3130 --- sonoff/language/it-IT.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 0eaca9337..5cb974df5 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 3c3ae73e606d56992b0d47016d6ebeb6205304c6 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:05:09 +0100 Subject: [PATCH 12/20] Language keys for MGC3130 --- sonoff/language/nl-NL.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 0567e0849..875bfd921 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From e08f2126b68fd9e53d2e4ecf1262ce618f402a29 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:05:34 +0100 Subject: [PATCH 13/20] Language keys for MGC3130 --- sonoff/language/pl-PL.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 678a7b770..e697966e5 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 87a9d3e0cf662525ac45a7e768dfcdad41770817 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:06:02 +0100 Subject: [PATCH 14/20] Language keys for MGC3130 --- sonoff/language/pt-BR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 712ea6a74..0336bac9a 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From ba6433ccf78960f6bc8236d6c2dee65fa7a35450 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:06:32 +0100 Subject: [PATCH 15/20] Language keys for MGC3130 --- sonoff/language/pt-PT.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 0bba501bd..7afd0b1bc 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -529,6 +529,9 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" + // Units #define D_UNIT_AMPERE "A" From 20d3343e852a0675ebbafb5829dd77b8c74a9919 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:07:13 +0100 Subject: [PATCH 16/20] Language keys for MGC3130 --- sonoff/language/ru-RU.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index f9062a572..bc6383476 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "А" From 08ae15db6f79e23b4bf8584243002c60644141f4 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:07:42 +0100 Subject: [PATCH 17/20] Language keys for MGC3130 --- sonoff/language/tr-TR.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index f892fafbb..f5bf3ed8f 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "A" From 0d6df5ed6155e7a953adddb1e102aaf516704856 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:08:19 +0100 Subject: [PATCH 18/20] Language keys for MGC3130 --- sonoff/language/uk-UK.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 4c290613a..c6303e243 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "А" From ae9d66bfa99c2d41f2bc8610755e8edae1187d15 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:08:46 +0100 Subject: [PATCH 19/20] Language keys for MGC3130 --- sonoff/language/zh-CN.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index fe6dabe8d..746eb0b86 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "安" From 02dd07cb95cb28f2c31943645cbef8c79db82fe2 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Nov 2018 21:09:17 +0100 Subject: [PATCH 20/20] Language keys for MGC3130 --- sonoff/language/zh-TW.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 92a805587..a6894dc1e 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -529,6 +529,8 @@ #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer" +#define D_SENSOR_MGC3130_RESET "MGC3130 Reset" // Units #define D_UNIT_AMPERE "安"