Merge pull request 'gw/testing' (#4) from gw/testing into gateway
Reviewed-on: #4
This commit is contained in:
commit
ab04a72996
18
.drone.yml
18
.drone.yml
@ -1,24 +1,38 @@
|
|||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: exec
|
type: exec
|
||||||
name: upload gateway firmare
|
name: gateway pipeline
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
arch: arm
|
arch: arm
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: upload
|
- name: native tests
|
||||||
|
commands:
|
||||||
|
- cd gateway
|
||||||
|
- pio test -e native
|
||||||
|
|
||||||
|
- name: embedded tests
|
||||||
|
commands:
|
||||||
|
- cd gateway
|
||||||
|
- LD_LIBRARY_PATH=~/.platformio/packages/tool-simavr/lib/ pio test -e embedded --without-uploading
|
||||||
|
|
||||||
|
- name: upload firmware
|
||||||
commands:
|
commands:
|
||||||
- cd gateway
|
- cd gateway
|
||||||
- service ser2net stop
|
- service ser2net stop
|
||||||
- pio run -e pro-mini
|
- pio run -e pro-mini
|
||||||
- echo -n 'reset' > /dev/ttyUSB0; sleep 1s; avrdude -patmega328p -carduino -P/dev/ttyUSB0 -b115200 -D -Uflash:w:.pio/build/pro-mini/firmware.hex:i -v
|
- echo -n 'reset' > /dev/ttyUSB0; sleep 1s; avrdude -patmega328p -carduino -P/dev/ttyUSB0 -b115200 -D -Uflash:w:.pio/build/pro-mini/firmware.hex:i -v
|
||||||
- service ser2net start
|
- service ser2net start
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- gateway
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
- gateway
|
- gateway
|
||||||
|
- gw/*
|
||||||
|
|
||||||
node:
|
node:
|
||||||
host: homebox
|
host: homebox
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Protocol.h"
|
#include "Protocol.h"
|
||||||
|
#include "RcDecoder.h"
|
||||||
#define RC_STATE(value) value & 0x1
|
|
||||||
#define RC_DEVICE(value) (value >> 1) & 0x1F
|
|
||||||
#define RC_GROUP(value) (value >> 6) & 0x1F
|
|
||||||
|
|
||||||
class Protocol_1 : public Protocol {
|
class Protocol_1 : public Protocol {
|
||||||
|
|
||||||
@ -22,48 +19,11 @@ public:
|
|||||||
void toJson(unsigned long value, JsonDocument& jsonDoc) override {
|
void toJson(unsigned long value, JsonDocument& jsonDoc) override {
|
||||||
JsonObject rcSwitch = jsonDoc.createNestedObject("rcSwitch");
|
JsonObject rcSwitch = jsonDoc.createNestedObject("rcSwitch");
|
||||||
rcSwitch["protocol"] = protocol;
|
rcSwitch["protocol"] = protocol;
|
||||||
Decoder decoder;
|
RcDecoder decoder;
|
||||||
decoder.decode(value);
|
decoder.decode(value);
|
||||||
rcSwitch["state"] = decoder.state;
|
rcSwitch["state"] = decoder.state;
|
||||||
rcSwitch["group"] = String(decoder.group, BIN);
|
rcSwitch["group"] = String(decoder.group, BIN);
|
||||||
rcSwitch["channel"] = decoder.device;
|
rcSwitch["channel"] = decoder.device;
|
||||||
rcSwitch["raw_value"] = value;
|
rcSwitch["raw_value"] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
struct Decoder {
|
|
||||||
bool state;
|
|
||||||
char group;
|
|
||||||
byte device;
|
|
||||||
|
|
||||||
void decode(unsigned long value) {
|
|
||||||
value = value >> 2;
|
|
||||||
unsigned long res = 0;
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
res |= ((value & 1) ^ 1) << i;
|
|
||||||
value = value >> 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = RC_STATE(res);
|
|
||||||
group = RC_GROUP(res);
|
|
||||||
switch (RC_DEVICE(res)) {
|
|
||||||
case 0b10000:
|
|
||||||
device = 1;
|
|
||||||
break;
|
|
||||||
case 0b01000:
|
|
||||||
device = 2;
|
|
||||||
break;
|
|
||||||
case 0b00100:
|
|
||||||
device = 3;
|
|
||||||
break;
|
|
||||||
case 0b00010:
|
|
||||||
device = 4;
|
|
||||||
break;
|
|
||||||
case 0b00001:
|
|
||||||
device = 5;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Protocol.h"
|
#include "Protocol.h"
|
||||||
#include "Tiny.h"
|
#include "TinyComponent.h"
|
||||||
|
|
||||||
class Protocol_2 : public Protocol {
|
class Protocol_2 : public Protocol {
|
||||||
|
|
||||||
@ -33,35 +33,4 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
bool buildSensorJson(unsigned long value, JsonDocument& jsonDoc) {
|
|
||||||
JsonObject sensor = jsonDoc.createNestedObject("sensor");
|
|
||||||
sensor["id"] = ID(value);
|
|
||||||
|
|
||||||
float voltage = (float)GET_VCC(value) / 1000;
|
|
||||||
if (voltage != 0) {
|
|
||||||
JsonObject diagnostic = sensor.createNestedObject("diagnostic");
|
|
||||||
diagnostic["voltage"] = voltage;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (GET_TYPE(value)) {
|
|
||||||
case SensorType::GENERIC:
|
|
||||||
sensor["value"] = GET_VALUE(value);
|
|
||||||
break;
|
|
||||||
case SensorType::TEMPERATURE:
|
|
||||||
sensor["temperature"] = (float)GET_TEMP(value) / 10;
|
|
||||||
break;
|
|
||||||
case SensorType::HUMIDITY:
|
|
||||||
sensor["humidity"] = (float)GET_HUMIDITY(value) / 10;
|
|
||||||
break;
|
|
||||||
case SensorType::CONTACT:
|
|
||||||
sensor["state"] = GET_STATE(value) ? "on" : "off";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
38
gateway/include/RcDecoder.h
Normal file
38
gateway/include/RcDecoder.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#define RC_STATE(value) value & 0x1
|
||||||
|
#define RC_DEVICE(value) (value >> 1) & 0x1F
|
||||||
|
#define RC_GROUP(value) (value >> 6) & 0x1F
|
||||||
|
|
||||||
|
struct RcDecoder {
|
||||||
|
bool state;
|
||||||
|
char group;
|
||||||
|
unsigned char device;
|
||||||
|
|
||||||
|
void decode(unsigned long value) {
|
||||||
|
value = value >> 2;
|
||||||
|
unsigned long res = 0;
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
res |= ((value & 1) ^ 1) << i;
|
||||||
|
value = value >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = RC_STATE(res);
|
||||||
|
group = RC_GROUP(res);
|
||||||
|
switch (RC_DEVICE(res)) {
|
||||||
|
case 0b10000:
|
||||||
|
device = 1;
|
||||||
|
break;
|
||||||
|
case 0b01000:
|
||||||
|
device = 2;
|
||||||
|
break;
|
||||||
|
case 0b00100:
|
||||||
|
device = 3;
|
||||||
|
break;
|
||||||
|
case 0b00010:
|
||||||
|
device = 4;
|
||||||
|
break;
|
||||||
|
case 0b00001:
|
||||||
|
device = 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
32
gateway/include/TinyComponent.h
Normal file
32
gateway/include/TinyComponent.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include "Tiny.h"
|
||||||
|
|
||||||
|
bool buildSensorJson(unsigned long value, JsonDocument& jsonDoc) {
|
||||||
|
JsonObject sensor = jsonDoc.createNestedObject("sensor");
|
||||||
|
sensor["id"] = ID(value);
|
||||||
|
|
||||||
|
float voltage = (float)GET_VCC(value) / 1000;
|
||||||
|
if (voltage != 0) {
|
||||||
|
JsonObject diagnostic = sensor.createNestedObject("diagnostic");
|
||||||
|
diagnostic["voltage"] = voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (GET_TYPE(value)) {
|
||||||
|
case SensorType::GENERIC:
|
||||||
|
sensor["value"] = GET_VALUE(value);
|
||||||
|
break;
|
||||||
|
case SensorType::TEMPERATURE:
|
||||||
|
sensor["temperature"] = (float)GET_TEMP(value) / 10;
|
||||||
|
break;
|
||||||
|
case SensorType::HUMIDITY:
|
||||||
|
sensor["humidity"] = (float)GET_HUMIDITY(value) / 10;
|
||||||
|
break;
|
||||||
|
case SensorType::CONTACT:
|
||||||
|
sensor["state"] = GET_STATE(value) ? "on" : "off";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@ -21,3 +21,29 @@ lib_deps =
|
|||||||
adafruit/DHT sensor library@1.3.10
|
adafruit/DHT sensor library@1.3.10
|
||||||
build_flags = -D DHT_SENSOR=0
|
build_flags = -D DHT_SENSOR=0
|
||||||
upload_port = /dev/ttyUSB0
|
upload_port = /dev/ttyUSB0
|
||||||
|
|
||||||
|
[env:native]
|
||||||
|
platform = native
|
||||||
|
test_filter = test_native
|
||||||
|
|
||||||
|
[env:embedded]
|
||||||
|
platform = atmelavr
|
||||||
|
framework = arduino
|
||||||
|
board = miniatmega328
|
||||||
|
lib_extra_dirs =
|
||||||
|
../libraries
|
||||||
|
lib_deps =
|
||||||
|
sui77/rc-switch@^2.6.3
|
||||||
|
bblanchon/ArduinoJson@6.16.1
|
||||||
|
|
||||||
|
platform_packages =
|
||||||
|
platformio/tool-simavr
|
||||||
|
test_speed = 9600
|
||||||
|
test_testing_command =
|
||||||
|
${platformio.packages_dir}/tool-simavr/bin/simavr
|
||||||
|
-m
|
||||||
|
atmega328p
|
||||||
|
-f
|
||||||
|
16000000L
|
||||||
|
${platformio.build_dir}/${this.__env__}/firmware.elf
|
||||||
|
test_filter = test_embedded
|
||||||
|
|||||||
116
gateway/test/test_embedded/sensor_builder.cpp
Normal file
116
gateway/test/test_embedded/sensor_builder.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <unity.h>
|
||||||
|
#include "TinyComponent.h"
|
||||||
|
|
||||||
|
void setUp(void) {
|
||||||
|
// set stuff up here
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void) {
|
||||||
|
// clean stuff up here
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_unknown_sensor_type(void) {
|
||||||
|
StaticJsonDocument<200> jsonDoc;
|
||||||
|
unsigned long value = TYPE(0);
|
||||||
|
TEST_ASSERT_EQUAL(false, buildSensorJson(value, jsonDoc));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_max_temp(void) {
|
||||||
|
StaticJsonDocument<200> jsonDoc;
|
||||||
|
unsigned long value = TEMP(1023) | TYPE(SensorType::TEMPERATURE);
|
||||||
|
TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc));
|
||||||
|
|
||||||
|
JsonObject sensor = jsonDoc["sensor"];
|
||||||
|
TEST_ASSERT_EQUAL(102.3, sensor["temperature"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_overflow_value(void) {
|
||||||
|
StaticJsonDocument<200> jsonDoc;
|
||||||
|
unsigned long value = VALUE(1024) | TYPE(SensorType::GENERIC);
|
||||||
|
TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc));
|
||||||
|
|
||||||
|
JsonObject sensor = jsonDoc["sensor"];
|
||||||
|
TEST_ASSERT_EQUAL(0, sensor["value"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_max_voltage(void) {
|
||||||
|
StaticJsonDocument<200> jsonDoc;
|
||||||
|
unsigned long value = VCC(8191) | TYPE(SensorType::GENERIC);
|
||||||
|
TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc));
|
||||||
|
|
||||||
|
JsonObject diagnostic = jsonDoc["sensor"]["diagnostic"];
|
||||||
|
TEST_ASSERT_EQUAL(8.191, diagnostic["voltage"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_overflow_voltage(void) {
|
||||||
|
StaticJsonDocument<200> jsonDoc;
|
||||||
|
unsigned long value = VCC(8192) | TYPE(SensorType::GENERIC);
|
||||||
|
TEST_ASSERT_EQUAL(true, buildSensorJson(value, jsonDoc));
|
||||||
|
|
||||||
|
JsonObject diagnostic = jsonDoc["sensor"]["diagnostic"];
|
||||||
|
TEST_ASSERT_EQUAL(0, diagnostic["voltage"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
JsonObject sensor = jsonDoc["sensor"];
|
||||||
|
TEST_ASSERT_EQUAL(SensorId::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));
|
||||||
|
|
||||||
|
JsonObject sensor = jsonDoc["sensor"];
|
||||||
|
TEST_ASSERT_EQUAL(SensorId::TEMP_SENSOR, sensor["id"]);
|
||||||
|
TEST_ASSERT_EQUAL(32, sensor["temperature"]);
|
||||||
|
|
||||||
|
JsonObject diagnostic = sensor["diagnostic"];
|
||||||
|
TEST_ASSERT_EQUAL(2.847, diagnostic["voltage"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
JsonObject sensor = jsonDoc["sensor"];
|
||||||
|
TEST_ASSERT_EQUAL(SensorId::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));
|
||||||
|
|
||||||
|
JsonObject sensor = jsonDoc["sensor"];
|
||||||
|
TEST_ASSERT_EQUAL(SensorId::OIL_SENSOR, sensor["id"]);
|
||||||
|
TEST_ASSERT_EQUAL(200, sensor["value"]);
|
||||||
|
|
||||||
|
JsonObject diagnostic = sensor["diagnostic"];
|
||||||
|
TEST_ASSERT_EQUAL(2.847, diagnostic["voltage"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
UNITY_BEGIN();
|
||||||
|
RUN_TEST(test_unknown_sensor_type);
|
||||||
|
RUN_TEST(test_max_temp);
|
||||||
|
RUN_TEST(test_overflow_value);
|
||||||
|
RUN_TEST(test_max_voltage);
|
||||||
|
RUN_TEST(test_overflow_voltage);
|
||||||
|
RUN_TEST(test_temp_sensor);
|
||||||
|
RUN_TEST(test_temp_sensor_with_voltage);
|
||||||
|
RUN_TEST(test_oil_sensor);
|
||||||
|
RUN_TEST(test_oil_sensor_with_voltage);
|
||||||
|
UNITY_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
}
|
||||||
35
gateway/test/test_native/decoder.cpp
Normal file
35
gateway/test/test_native/decoder.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include <unity.h>
|
||||||
|
#include "RcDecoder.h"
|
||||||
|
|
||||||
|
RcDecoder d;
|
||||||
|
|
||||||
|
void setUp(void) {
|
||||||
|
// set stuff up here
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void) {
|
||||||
|
// clean stuff up here
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_1_2_on(void) {
|
||||||
|
d.decode(5574993);
|
||||||
|
TEST_ASSERT_EQUAL(true, d.state);
|
||||||
|
TEST_ASSERT_EQUAL(1, d.group);
|
||||||
|
TEST_ASSERT_EQUAL(2, d.device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_1_1_off(void) {
|
||||||
|
d.decode(5571924);
|
||||||
|
TEST_ASSERT_EQUAL(false, d.state);
|
||||||
|
TEST_ASSERT_EQUAL(1, d.group);
|
||||||
|
TEST_ASSERT_EQUAL(1, d.device);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
UNITY_BEGIN();
|
||||||
|
RUN_TEST(test_1_2_on);
|
||||||
|
RUN_TEST(test_1_1_off);
|
||||||
|
UNITY_END();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,28 +1,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define MASK_ID 0x1F
|
||||||
|
#define MASK_VCC 0x1FFF
|
||||||
|
#define MASK_VALUE 0x3FF
|
||||||
|
#define MASK_STATE 0x1
|
||||||
|
#define MASK_TYPE 0xF
|
||||||
|
|
||||||
#define ID(value) (value & 0x1F)
|
#define ID(value) (value & 0x1F)
|
||||||
#define VCC(value) ((value & 0x1FFF) << 5)
|
#define VCC(value) (((unsigned long)value & MASK_VCC) << 5)
|
||||||
#define TEMP(value) (((unsigned long)value & 0x2FF) << 18)
|
#define TEMP(value) (((unsigned long)value & MASK_VALUE) << 18)
|
||||||
#define HUMIDITY(value) (((unsigned long)value & 0x2FF) << 18)
|
#define HUMIDITY(value) (((unsigned long)value & MASK_VALUE) << 18)
|
||||||
#define VALUE(value) (((unsigned long)value & 0x2FF) << 18)
|
#define VALUE(value) (((unsigned long)value & MASK_VALUE) << 18)
|
||||||
#define STATE(value) ((value & 0x1) << 27)
|
#define STATE(value) ((value & MASK_STATE) << 27)
|
||||||
#define TYPE(value) (((unsigned long)value & 0xF) << 28)
|
#define TYPE(value) (((unsigned long)value & MASK_TYPE) << 28)
|
||||||
|
|
||||||
#define GET_TYPE(value) (((unsigned long)value >> 28) & 0xF)
|
#define GET_TYPE(value) (((unsigned long)value >> 28) & MASK_TYPE)
|
||||||
#define GET_STATE(value) ((value >> 27) & 0x1)
|
#define GET_STATE(value) ((value >> 27) & MASK_STATE)
|
||||||
#define GET_TEMP(value) (((unsigned long)value >> 18) & 0x2FF)
|
#define GET_TEMP(value) (((unsigned long)value >> 18) & MASK_VALUE)
|
||||||
#define GET_HUMIDITY(value) (((unsigned long)value >> 18) & 0x2FF)
|
#define GET_HUMIDITY(value) (((unsigned long)value >> 18) & MASK_VALUE)
|
||||||
#define GET_VALUE(value) (((unsigned long)value >> 18) & 0x2FF)
|
#define GET_VALUE(value) (((unsigned long)value >> 18) & MASK_VALUE)
|
||||||
#define GET_VCC(value) (((unsigned long)value >> 5) & 0x1FFF)
|
#define GET_VCC(value) (((unsigned long)value >> 5) & MASK_VCC)
|
||||||
|
|
||||||
enum SensorType {
|
enum SensorType : unsigned short {
|
||||||
GENERIC = 4,
|
GENERIC = 4,
|
||||||
HUMIDITY = 5,
|
HUMIDITY = 5,
|
||||||
TEMPERATURE = 6,
|
TEMPERATURE = 6,
|
||||||
CONTACT = 7
|
CONTACT = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SensorId : int {
|
enum SensorId : unsigned short {
|
||||||
WINDOW1 = 1,
|
WINDOW1 = 1,
|
||||||
WINDOW2 = 2,
|
WINDOW2 = 2,
|
||||||
WATER_SENSOR = 3,
|
WATER_SENSOR = 3,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user