diff --git a/devices/presence_sensor/.gitignore b/devices/presence_sensor/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/devices/presence_sensor/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/devices/presence_sensor/README.md b/devices/presence_sensor/README.md new file mode 100644 index 0000000..11a8e19 --- /dev/null +++ b/devices/presence_sensor/README.md @@ -0,0 +1,5 @@ +# Presence ticker + +It sends state on regular intervals, so that presence of the bearer can be tracked. + +![Schematics](docs/presence_sensor_bb.png) diff --git a/devices/presence_sensor/docs/presence_sensor.fzz b/devices/presence_sensor/docs/presence_sensor.fzz new file mode 100644 index 0000000..2cdd17a --- /dev/null +++ b/devices/presence_sensor/docs/presence_sensor.fzz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09a14fc2865ec4834054f390ba1b4683c393835ac0aed6e68e30e19e7dae4982 +size 6814 diff --git a/devices/presence_sensor/docs/presence_sensor_bb.png b/devices/presence_sensor/docs/presence_sensor_bb.png new file mode 100644 index 0000000..13c3656 --- /dev/null +++ b/devices/presence_sensor/docs/presence_sensor_bb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1603cb8e433a7ee1fd0a2300dfaf574386b5e681dd17ccebe104cfc635ed038e +size 120232 diff --git a/devices/presence_sensor/include/README b/devices/presence_sensor/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/devices/presence_sensor/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/devices/presence_sensor/lib/README b/devices/presence_sensor/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/devices/presence_sensor/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/devices/presence_sensor/platformio.ini b/devices/presence_sensor/platformio.ini new file mode 100644 index 0000000..0025c14 --- /dev/null +++ b/devices/presence_sensor/platformio.ini @@ -0,0 +1,24 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:attiny85] +platform = atmelavr +board = attiny85 +framework = arduino +lib_deps = + sui77/rc-switch @ ^2.6.4 +lib_extra_dirs = + ../../lib +upload_protocol = stk500v1 +upload_flags = + -P$UPLOAD_PORT + -b$UPLOAD_SPEED +upload_port = /dev/ttyACM0 +upload_speed = 19200 diff --git a/devices/presence_sensor/src/presence_sensor.cpp b/devices/presence_sensor/src/presence_sensor.cpp new file mode 100644 index 0000000..a11a866 --- /dev/null +++ b/devices/presence_sensor/src/presence_sensor.cpp @@ -0,0 +1,37 @@ +#include +#include +#include "ContactSensor.h" + +#define MINUTES(value) (uint16_t)(value*60/8) // minutes*60(seconds)/8s(WDT) +#define HOURS(value) (uint16_t)(MINUTES(value)*60) + +#define SEND_INTERVAL MINUTES(2) +#define SEND_VCC_INTERVAL HOURS(6) + +// Pins +#define SENDER_PIN PIN_B2 + +volatile uint16_t counter = 0; +ContactSensor sensor(PRESENCE_SENSOR); + +void setup() { + + TinySwitch::setup(SENDER_PIN); + TinyPower::setup(); + TinyPower::enableWdt(WDTO_8S); +} + +void loop() { + if (counter == 0) { + sensor.sendStateAndVoltage(false); + } else if (counter % SEND_INTERVAL == 0) { + sensor.sendState(false); + } + TinyPower::sleep(); +} + +ISR(WDT_vect) { + if (++counter % SEND_VCC_INTERVAL == 0) { + counter = 0; + } +} diff --git a/devices/presence_sensor/test/README b/devices/presence_sensor/test/README new file mode 100644 index 0000000..b94d089 --- /dev/null +++ b/devices/presence_sensor/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html diff --git a/include/TinyComponent.h b/include/TinyComponent.h index 725fce1..999d5f7 100644 --- a/include/TinyComponent.h +++ b/include/TinyComponent.h @@ -24,7 +24,7 @@ bool buildSensorJson(unsigned long value, JsonDocument& jsonDoc) { sensor["humidity"] = (float)GET_HUMIDITY(value) / 10; break; case SensorType::CONTACT: - sensor["state"] = GET_STATE(value) ? "on" : "off"; + sensor["state"] = GET_STATE(value) ? "ON" : "OFF"; break; default: return false; diff --git a/include/devices.h b/include/devices.h index fad2dd5..35acd0c 100644 --- a/include/devices.h +++ b/include/devices.h @@ -15,46 +15,53 @@ unordered_map p1Switches; auto gatewayDevice = &DeviceConfig::create(MAIN_DEVICE_ID).withName("RC Gateway").withManufacturer("Adafruit").withModel("Huzzah Esp8266"); -Sensor* buildRoomSensor(const char* id) { - DeviceConfig* device = &DeviceConfig::create(id) +auto roomSensor = Builder::instance(TEMP_SENSOR) + .asDevice(&DeviceConfig::create(TEMP_SENSOR) .withName("Servers room") .withManufacturer("Atmel") .withModel("AtTiny85") .withArea("Basement") - .withParent(gatewayDevice); - return Builder::instance(id) - .asDevice(device) - .withValueTemplate("{{ value_json.sensor.temperature }}") - .addDiagnostic(new VoltageSensor{id, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"}) - .addDiagnostic(new BatterySensor{id, "Battery level", "{{ ((value_json.sensor.diagnostic.voltage|float-2.5)|round(2)*100/2)|int }}"}) - .build(); -} + .withParent(gatewayDevice)) + .withValueTemplate("{{ value_json.sensor.temperature }}") + .addDiagnostic(new VoltageSensor{TEMP_SENSOR, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"}) + .addDiagnostic(new BatterySensor{TEMP_SENSOR, "Battery level", "{{ ((value_json.sensor.diagnostic.voltage|float-2.5)|round(2)*100/2)|int }}"}) + .build(); -Sensor* buildTankSensor(const char* id) { - DeviceConfig* device = &DeviceConfig::create(id) +auto tankSensor = Builder::instance(new Sensor{ "Level", OIL_SENSOR }) + .asDevice(&DeviceConfig::create(OIL_SENSOR) .withName("Oil tank") .withManufacturer("Arduino") .withModel("Pro Mini") .withArea("Basement") - .withParent(gatewayDevice); - return Builder::instance(new Sensor{ "Level", id }) - .asDevice(device) - .withUnitMeasure("%") + .withParent(gatewayDevice)) + .withUnitMeasure("%") + .withSensorStateClass(MEASUREMENT) + .withIcon("mdi:hydraulic-oil-level") + .withValueTemplate("{{ 100 - ((value_json.sensor.value-12)|float*100/120)|round(2) }}") + .addSecondary( + Builder::instance(new Sensor{ "Depth", OIL_SENSOR }) + .withDeviceClass("distance") + .withUnitMeasure("cm") .withSensorStateClass(MEASUREMENT) - .withIcon("mdi:hydraulic-oil-level") - .withValueTemplate("{{ 100 - ((value_json.sensor.value-12)|float*100/120)|round(2) }}") - .addSecondary( - Builder::instance(new Sensor{ "Depth", id }) - .withDeviceClass("distance") - .withUnitMeasure("cm") - .withSensorStateClass(MEASUREMENT) - .withValueTemplate("{{ value_json.sensor.value }}") - .build() - ) - .addDiagnostic(new VoltageSensor{id, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"}) - .addDiagnostic(new BatterySensor{id, "Battery level", "{{ ((value_json.sensor.diagnostic.voltage|float-4.0)|round(2)*100/2.4)|int }}"}) - .build(); -} + .withValueTemplate("{{ value_json.sensor.value }}") + .build() + ) + .addDiagnostic(new VoltageSensor{OIL_SENSOR, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"}) + .addDiagnostic(new BatterySensor{OIL_SENSOR, "Battery level", "{{ ((value_json.sensor.diagnostic.voltage|float-4.0)|round(2)*100/2.4)|int }}"}) + .build(); + +auto presenceTracker = Builder::instance(PRESENCE_SENSOR) + .asDevice(&DeviceConfig::create(PRESENCE_SENSOR) + .withName("Kid presence") + .withManufacturer("Atmel") + .withModel("AtTiny85") + .withParent(gatewayDevice)) + .withValueTemplate("{{ value_json.sensor.state }}") + .addDiagnostic(new VoltageSensor{PRESENCE_SENSOR, "Battery voltage", "{{ value_json.sensor.diagnostic.voltage }}"}) + .addDiagnostic(new BatterySensor{PRESENCE_SENSOR, "Battery level", "{{ ((value_json.sensor.diagnostic.voltage|float-2.7)|round(2)*100/0.6)|int }}"}) + .withOffDelaySeconds(5*60) + .withDeviceClass("presence") + .build(); struct PollinSwitch : Switch { constexpr static const char* man = "Pollin"; @@ -143,8 +150,3 @@ Command* commands[] = { new PollinSwitch{"00011", 4, "homebox"}, new PollinSwitch{"11111", 4, "Train", "Playroom"} }; - -Sensor* sensors[] = { - buildRoomSensor("4"), - buildTankSensor("7") -}; diff --git a/include/huzzah.h b/include/huzzah.h index 60b31ad..6f2ac7d 100644 --- a/include/huzzah.h +++ b/include/huzzah.h @@ -13,6 +13,8 @@ Scheduler ts; #include "wifi.h" #include "webserver.h" +#define RAW_TOPIC MAIN_DEVICE_ID "/raw" + namespace Board { Task tReadCommand(TASK_IMMEDIATE, TASK_FOREVER, [](){ @@ -98,14 +100,14 @@ namespace Board { void parseSensors(JsonDocument& jsonDoc, char* message) { JsonObjectConst json = jsonDoc["sensor"]; string id = to_string((unsigned int)json["id"]); - auto sensor = Sensor::mapSensors[id]; + auto sensor = GenericSensor::mapSensors[id]; if (sensor) sensor->updateState(message); } void publishResponse(JsonDocument& jsonDoc) { char message[255]; serializeJson(jsonDoc, message); - Mqtt::publish("homeassistant/sensor/rc-gateway/raw", message); + Mqtt::publish(RAW_TOPIC, message); if (jsonDoc.containsKey("rcSwitch")) parseSwitches(jsonDoc); if (jsonDoc.containsKey("sensor")) parseSensors(jsonDoc, message); } @@ -113,7 +115,7 @@ namespace Board { void handleJsonError(JsonDocument& jsonError) { char message[255]; serializeJson(jsonError, message); - Mqtt::publish("homeassistant/sensor/rc-gateway/raw", message); + Mqtt::publish(RAW_TOPIC, message); } } // {"rcSwitch":{"protocol":1,"state":false,"group":"11111","channel":4}} \ No newline at end of file diff --git a/lib/Tiny/ContactSensor.h b/lib/Tiny/ContactSensor.h index dd3e702..ab15b29 100644 --- a/lib/Tiny/ContactSensor.h +++ b/lib/Tiny/ContactSensor.h @@ -6,9 +6,7 @@ class ContactSensor: public TinySensor { SensorType sensorType = CONTACT; public: - ContactSensor(short id) : - TinySensor(id) { - } + ContactSensor(SensorId id) : TinySensor(id) {} void sendStateAndVoltage(bool state) { sendInfo(ID(id) | VCC(readVcc()) | STATE(!state) | TYPE(sensorType)); diff --git a/lib/Tiny/GenericSensor.h b/lib/Tiny/GenericSensor.h index 2522267..110a9e0 100644 --- a/lib/Tiny/GenericSensor.h +++ b/lib/Tiny/GenericSensor.h @@ -6,9 +6,7 @@ class GenericSensor : public TinySensor { SensorType sensorType = GENERIC; public: - GenericSensor(short id) : - TinySensor(id) { - } + GenericSensor(SensorId id) : TinySensor(id) {} void sendValueAndVoltage(int value) { sendInfo(ID(id) | VCC(readVcc()) | VALUE(value) | TYPE(sensorType)); diff --git a/lib/Tiny/HumiditySensor.h b/lib/Tiny/HumiditySensor.h index 44a7db1..de59f4f 100644 --- a/lib/Tiny/HumiditySensor.h +++ b/lib/Tiny/HumiditySensor.h @@ -6,9 +6,7 @@ class HumiditySensor : public TinySensor { SensorType sensorType = HUMIDITY; public: - HumiditySensor(short id) : - TinySensor(id) { - } + HumiditySensor(SensorId id) : TinySensor(id) {} void sendHumidityAndVoltage(int humidity) { sendInfo(ID(id) | VCC(readVcc()) | HUMIDITY(humidity) | TYPE(sensorType)); diff --git a/lib/Tiny/TemperatureSensor.h b/lib/Tiny/TemperatureSensor.h index f3669e7..3d49bce 100644 --- a/lib/Tiny/TemperatureSensor.h +++ b/lib/Tiny/TemperatureSensor.h @@ -6,9 +6,7 @@ class TemperatureSensor : public TinySensor { SensorType sensorType = TEMPERATURE; public: - TemperatureSensor(short id) : - TinySensor(id) { - } + TemperatureSensor(SensorId id) : TinySensor(id) {} void sendTempAndVoltage(int temp) { sendInfo(ID(id) | VCC(readVcc()) | TEMP(temp) | TYPE(sensorType)); diff --git a/lib/Tiny/Tiny.h b/lib/Tiny/Tiny.h index 653be12..1c5e706 100644 --- a/lib/Tiny/Tiny.h +++ b/lib/Tiny/Tiny.h @@ -6,16 +6,16 @@ #define MASK_STATE 0x1 #define MASK_TYPE 0xF -#define ID(value) (value & 0x1F) +#define ID(value) ((unsigned long)value & MASK_ID) #define VCC(value) (((unsigned long)value & MASK_VCC) << 5) #define TEMP(value) (((unsigned long)value & MASK_VALUE) << 18) #define HUMIDITY(value) (((unsigned long)value & MASK_VALUE) << 18) #define VALUE(value) (((unsigned long)value & MASK_VALUE) << 18) -#define STATE(value) ((value & MASK_STATE) << 27) +#define STATE(value) (((unsigned long)value & MASK_STATE) << 27) #define TYPE(value) (((unsigned long)value & MASK_TYPE) << 28) #define GET_TYPE(value) (((unsigned long)value >> 28) & MASK_TYPE) -#define GET_STATE(value) ((value >> 27) & MASK_STATE) +#define GET_STATE(value) (((unsigned long)value >> 27) & MASK_STATE) #define GET_TEMP(value) (((unsigned long)value >> 18) & MASK_VALUE) #define GET_HUMIDITY(value) (((unsigned long)value >> 18) & MASK_VALUE) #define GET_VALUE(value) (((unsigned long)value >> 18) & MASK_VALUE) @@ -28,12 +28,29 @@ enum SensorType : unsigned short { CONTACT = 7 }; -enum SensorId : unsigned short { - WINDOW1 = 1, - WINDOW2 = 2, - WATER_SENSOR = 3, - TEMP_SENSOR = 4, - LIGHT_SENSOR = 5, - MOVEMENT_SENSOR = 6, - OIL_SENSOR = 7 -}; +class SensorId { + uint8_t value = 0; + char strValue[4]; + +public: + SensorId(uint8_t id) { + value = id; + snprintf(strValue, 4, "%d", value); + } + + operator uint8_t() { + return value; + } + + operator const char*() { + return strValue; + } +} +WINDOW1(1), +WINDOW2(2), +WATER_SENSOR(3), +TEMP_SENSOR(4), +LIGHT_SENSOR(5), +MOVEMENT_SENSOR(6), +OIL_SENSOR(7), +PRESENCE_SENSOR(8); diff --git a/lib/Tiny/TinySensor.h b/lib/Tiny/TinySensor.h index 8864fa5..673c160 100644 --- a/lib/Tiny/TinySensor.h +++ b/lib/Tiny/TinySensor.h @@ -7,7 +7,7 @@ using TinySwitch::sendInfo; class TinySensor { protected: - short id; + uint8_t id; long readVcc() { // Read 1.1V reference against AVcc @@ -33,7 +33,7 @@ protected: } public: - TinySensor(short id) { + TinySensor(SensorId id) { this->id = id; } }; diff --git a/platformio.ini b/platformio.ini index 18f0ae1..f7fb245 100644 --- a/platformio.ini +++ b/platformio.ini @@ -33,7 +33,7 @@ framework = arduino lib_deps = ${env.lib_deps} arkhipenko/TaskScheduler@^3.8.5 - https://git.hodos.ro/libraries/ha-mqtt.git@^1.10.0 + https://git.hodos.ro/libraries/ha-mqtt.git@^1.12.0 https://git.hodos.ro/libraries/wifi.git@^2.0.0 esphome/ESPAsyncWebServer-esphome@^3.4.0 upload_port = 192.168.6.161 diff --git a/rc-gateway.code-workspace b/rc-gateway.code-workspace index 5e605b8..91e8b64 100644 --- a/rc-gateway.code-workspace +++ b/rc-gateway.code-workspace @@ -1,13 +1,20 @@ { "folders": [ { + "name": "rc-gateway", "path": "." }, { + "name": "temp_sensor", "path": "devices/temp_sensor" }, { + "name": "oil_sensor", "path": "devices/oil_sensor" + }, + { + "name": "presence_sensor", + "path": "devices/presence_sensor" } ], "settings": { @@ -46,7 +53,39 @@ "iterator": "cpp", "memory": "cpp", "variant": "cpp", - "string_view": "cpp" + "string_view": "cpp", + "regex": "cpp", + "cstdint": "cpp", + "bit": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstdio": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "exception": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "mutex": "cpp", + "new": "cpp", + "ranges": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp" } } } \ No newline at end of file diff --git a/test/native/test_sensor_builder/sensor_builder.cpp b/test/native/test_sensor_builder/sensor_builder.cpp index db130f0..97d22b6 100644 --- a/test/native/test_sensor_builder/sensor_builder.cpp +++ b/test/native/test_sensor_builder/sensor_builder.cpp @@ -12,7 +12,7 @@ void tearDown(void) { void test_unknown_sensor_type(void) { StaticJsonDocument<200> jsonDoc; unsigned long value = TYPE(0); - TEST_ASSERT_EQUAL(false, buildSensorJson(value, jsonDoc)); + TEST_ASSERT_FALSE(buildSensorJson(value, jsonDoc)); } void test_max_temp(void) { @@ -24,6 +24,15 @@ void test_max_temp(void) { TEST_ASSERT_EQUAL(102.3, sensor["temperature"]); } +void test_max_value(void) { + StaticJsonDocument<200> jsonDoc; + unsigned long value = VALUE(1023) | TYPE(SensorType::GENERIC); + TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc)); + + JsonObject sensor = jsonDoc["sensor"]; + TEST_ASSERT_EQUAL(1023, sensor["value"]); +} + void test_overflow_value(void) { StaticJsonDocument<200> jsonDoc; unsigned long value = VALUE(1024) | TYPE(SensorType::GENERIC); @@ -36,7 +45,7 @@ void test_overflow_value(void) { void test_max_voltage(void) { StaticJsonDocument<200> jsonDoc; unsigned long value = VCC(8191) | TYPE(SensorType::GENERIC); - TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc)); + TEST_ASSERT_TRUE(buildSensorJson(value, jsonDoc)); JsonObject diagnostic = jsonDoc["sensor"]["diagnostic"]; TEST_ASSERT_EQUAL(8.191, diagnostic["voltage"]); @@ -45,7 +54,7 @@ void test_max_voltage(void) { void test_overflow_voltage(void) { StaticJsonDocument<200> jsonDoc; unsigned long value = VCC(8192) | TYPE(SensorType::GENERIC); - TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc)); + TEST_ASSERT_TRUE(buildSensorJson(value, jsonDoc)); JsonObject diagnostic = jsonDoc["sensor"]["diagnostic"]; TEST_ASSERT_EQUAL(0, diagnostic["voltage"]); @@ -53,21 +62,21 @@ void test_overflow_voltage(void) { void test_temp_sensor(void) { StaticJsonDocument<200> jsonDoc; - unsigned long value = ID(SensorId::TEMP_SENSOR) | TEMP(210) | TYPE(SensorType::TEMPERATURE); - TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc)); + unsigned long value = ID(TEMP_SENSOR) | TEMP(210) | TYPE(SensorType::TEMPERATURE); + TEST_ASSERT_TRUE(buildSensorJson(value, jsonDoc)); JsonObject sensor = jsonDoc["sensor"]; - TEST_ASSERT_EQUAL(SensorId::TEMP_SENSOR, sensor["id"]); + TEST_ASSERT_EQUAL(TEMP_SENSOR, sensor["id"]); TEST_ASSERT_EQUAL(21, sensor["temperature"]); } void test_temp_sensor_with_voltage(void) { StaticJsonDocument<200> jsonDoc; - unsigned long value = ID(SensorId::TEMP_SENSOR) | TEMP(320) | TYPE(SensorType::TEMPERATURE) | VCC(2847L); - TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc)); + unsigned long value = ID(TEMP_SENSOR) | TEMP(320) | TYPE(SensorType::TEMPERATURE) | VCC(2847L); + TEST_ASSERT_TRUE(buildSensorJson(value, jsonDoc)); JsonObject sensor = jsonDoc["sensor"]; - TEST_ASSERT_EQUAL(SensorId::TEMP_SENSOR, sensor["id"]); + TEST_ASSERT_EQUAL(TEMP_SENSOR, sensor["id"]); TEST_ASSERT_EQUAL(32, sensor["temperature"]); JsonObject diagnostic = sensor["diagnostic"]; @@ -76,31 +85,55 @@ void test_temp_sensor_with_voltage(void) { void test_oil_sensor(void) { StaticJsonDocument<200> jsonDoc; - unsigned long value = ID(SensorId::OIL_SENSOR) | VALUE(150) | TYPE(SensorType::GENERIC); - TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc)); + unsigned long value = ID(OIL_SENSOR) | VALUE(150) | TYPE(SensorType::GENERIC); + TEST_ASSERT_TRUE(buildSensorJson(value, jsonDoc)); JsonObject sensor = jsonDoc["sensor"]; - TEST_ASSERT_EQUAL(SensorId::OIL_SENSOR, sensor["id"]); + TEST_ASSERT_EQUAL(OIL_SENSOR, sensor["id"]); TEST_ASSERT_EQUAL(150, sensor["value"]); } void test_oil_sensor_with_voltage(void) { StaticJsonDocument<200> jsonDoc; - unsigned long value = ID(SensorId::OIL_SENSOR) | TEMP(200) | TYPE(SensorType::GENERIC) | VCC(2847L); - TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc)); + unsigned long value = ID(OIL_SENSOR) | TEMP(200) | TYPE(SensorType::GENERIC) | VCC(2847L); + TEST_ASSERT_TRUE(buildSensorJson(value, jsonDoc)); JsonObject sensor = jsonDoc["sensor"]; - TEST_ASSERT_EQUAL(SensorId::OIL_SENSOR, sensor["id"]); + TEST_ASSERT_EQUAL(OIL_SENSOR, sensor["id"]); TEST_ASSERT_EQUAL(200, sensor["value"]); JsonObject diagnostic = sensor["diagnostic"]; TEST_ASSERT_EQUAL(2.847, diagnostic["voltage"]); } +void test_presence_sensor(void) { + StaticJsonDocument<200> jsonDoc; + unsigned long value = ID(PRESENCE_SENSOR) | STATE(1) | TYPE(SensorType::CONTACT); + TEST_ASSERT_TRUE(buildSensorJson(value, jsonDoc)); + + JsonObject sensor = jsonDoc["sensor"]; + TEST_ASSERT_EQUAL(PRESENCE_SENSOR, sensor["id"]); + TEST_ASSERT_EQUAL_STRING("ON", sensor["state"]); +} + +void test_presence_sensor_with_voltage(void) { + StaticJsonDocument<200> jsonDoc; + unsigned long value = ID(PRESENCE_SENSOR) | STATE(0) | TYPE(SensorType::CONTACT) | VCC(3847L); + TEST_ASSERT_TRUE(buildSensorJson(value, jsonDoc)); + + JsonObject sensor = jsonDoc["sensor"]; + TEST_ASSERT_EQUAL(PRESENCE_SENSOR, sensor["id"]); + TEST_ASSERT_EQUAL_STRING("OFF", sensor["state"]); + + JsonObject diagnostic = sensor["diagnostic"]; + TEST_ASSERT_EQUAL(3.847, diagnostic["voltage"]); +} + int main(int argc, char **argv) { UNITY_BEGIN(); RUN_TEST(test_unknown_sensor_type); RUN_TEST(test_max_temp); + RUN_TEST(test_max_value); RUN_TEST(test_overflow_value); RUN_TEST(test_max_voltage); RUN_TEST(test_overflow_voltage); @@ -108,6 +141,8 @@ int main(int argc, char **argv) { RUN_TEST(test_temp_sensor_with_voltage); RUN_TEST(test_oil_sensor); RUN_TEST(test_oil_sensor_with_voltage); + RUN_TEST(test_presence_sensor); + RUN_TEST(test_presence_sensor_with_voltage); UNITY_END(); return 0;