Skip to content

Commit

Permalink
[Initial work] Add decoder lib / tests, create docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
h2zero authored and 1technophile committed Sep 26, 2021
1 parent 770dcb1 commit 7b5b44e
Show file tree
Hide file tree
Showing 16 changed files with 1,147 additions and 1 deletion.
14 changes: 14 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
BasedOnStyle: Google
Language: Cpp
ColumnLimit: 0
IndentWidth: 2
TabWidth: 2
UseTab: Never
IndentPPDirectives: AfterHash
ReflowComments: false
SpacesBeforeTrailingComments: 1
AlignConsecutiveMacros: true
AlignTrailingComments: false
AccessModifierOffset: -2
DerivePointerAlignment: false
PointerAlignment: Left
160 changes: 160 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
name: Build

on: [push, pull_request]

jobs:
gcc:
name: GCC
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- gcc: "4.6"
- gcc: "4.7"
- gcc: "4.8"
- gcc: "4.9"
- gcc: "5"
- gcc: "6"
- gcc: "7"
cxxflags: -fsanitize=leak -fno-sanitize-recover=all
- gcc: "8"
cxxflags: -fsanitize=undefined -fno-sanitize-recover=all
- gcc: "9"
cxxflags: -fsanitize=address -fno-sanitize-recover=all
- gcc: "10"
- gcc: "11"
steps:
- name: Install
run: |
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty main'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty universe'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial main'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial universe'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic main'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic universe'
sudo add-apt-repository -yn 'deb http://mirrors.kernel.org/ubuntu hirsute main universe'
sudo apt-get update
sudo apt-get install -y gcc-${{ matrix.gcc }} g++-${{ matrix.gcc }}
- name: Checkout
uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init --recursive
- name: Configure
run: cmake -DCMAKE_BUILD_TYPE=Debug .
env:
CC: gcc-${{ matrix.gcc }}
CXX: g++-${{ matrix.gcc }}
CXXFLAGS: ${{ matrix.cxxflags }}
- name: Build
run: cmake --build .
- name: Test
run: ctest --output-on-failure -V -C Debug .
env:
UBSAN_OPTIONS: print_stacktrace=1

clang:
name: Clang
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- clang: "3.5"
cxxflags: "-stdlib=libc++"
- clang: "3.6"
cxxflags: "-stdlib=libc++"
- clang: "3.7"
cxxflags: "-stdlib=libc++"
- clang: "3.8"
cxxflags: "-stdlib=libc++"
- clang: "3.9"
cxxflags: "-stdlib=libc++"
- clang: "4.0"
cxxflags: "-stdlib=libc++"
- clang: "5.0"
- clang: "6.0"
- clang: "7"
- clang: "8"
cxxflags: -fsanitize=leak -fno-sanitize-recover=all
- clang: "9"
cxxflags: -fsanitize=undefined -fno-sanitize-recover=all
- clang: "10"
cxxflags: -fsanitize=address -fno-sanitize-recover=all
steps:
- name: Install
run: |
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty main'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty universe'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial main'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial universe'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic main'
sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic universe'
sudo apt-get update
sudo apt-get install -y clang-${{ matrix.clang }}
- name: Checkout
uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init --recursive
- name: Configure
run: cmake -DCMAKE_BUILD_TYPE=Debug .
env:
CC: clang-${{ matrix.clang }}
CXX: clang++-${{ matrix.clang }}
CXXFLAGS: >-
${{ matrix.cxxflags }}
${{ contains(matrix.cxxflags, 'libc++') && '-I/usr/lib/llvm-10/include/c++/v1/' || '' }}
- name: Build
run: cmake --build .
- name: Test
run: ctest --output-on-failure -V -C Debug .
env:
UBSAN_OPTIONS: print_stacktrace=1

xcode:
name: XCode
needs: clang
runs-on: macos-10.15
strategy:
fail-fast: false
matrix:
include:
- xcode: "10.3"
- xcode: "11.7"
- xcode: "12.4"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init --recursive
- name: Select XCode version
run: sudo xcode-select --switch /Applications/Xcode_${{ matrix.xcode }}.app
- name: Configure
run: cmake -DCMAKE_BUILD_TYPE=Debug .
- name: Build
run: cmake --build .
- name: Test
run: ctest --output-on-failure -V -C Debug .

msvc:
name: Visual Studio
strategy:
fail-fast: false
matrix:
include:
- os: windows-2016
- os: windows-2019
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init --recursive
- name: Configure
run: cmake -DCMAKE_BUILD_TYPE=Debug .
- name: Build
run: cmake --build .
- name: Test
run: ctest --output-on-failure -V -C Debug .


3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/build
.vscode

3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "src/arduino_json"]
path = src/arduino_json
url = https://github.com/bblanchon/ArduinoJson.git
26 changes: 26 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.3)

project(1decoder VERSION 0.1.0)

add_library(1decoder
src/decoder.cpp
)

target_include_directories(1decoder
PUBLIC
$<INSTALL_INTERFACE:arduino_json>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/arduino_json/src>
${CMAKE_CURRENT_SOURCE_DIR}/src
)

target_compile_features(1decoder PRIVATE cxx_std_11)

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
include(CTest)
endif()

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
include(tests/CompileOptions.cmake)
add_subdirectory(tests)
endif()

118 changes: 117 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,117 @@
# 1decoder
# 1decoder

# Using

Call `decodeBLEJson(JsonObject)` with the input being of the Arduino JSON JsonObject type. If the device is known the JsonObject will have the decoded device data added to it.

### Example
Input JsonObject:
```
{
"servicedata": "712098000163b6658d7cc40d0410024001"
}
```

JsonObject after decoding:
```
{
"servicedata": "712098000163b6658d7cc40d0410024001"
"brand":"Xiaomi",
"model":"miflora",
"model_id":"HHCCJCY01HHCC",
"tempc":32,
"tempf":89.6
}
```

# Adding device decoding

Device decode specifications are located in the [device_json.h](src/device_json.h) file. The format is:
```
R""""(
{
"brand":"Xiaomi",
"model":"miflora",
"model_id":"HHCCJCY01HHCC",
"condition":["servicedata", "contain", "209800"],
"properties":{
"tempc":{
"condition":["servicedata", 25, "4"],
"decoder":["value_from_hex_data", "servicedata", 30, 4, true],
"post_proc":['/', 10]
},
"moi":{
"condition":["servicedata", 25, "8"],
"decoder":["value_from_hex_data", "servicedata", 30, 2, false]
},
"lux":{
"condition":["servicedata", 25, "7"],
"decoder":["value_from_hex_data", "servicedata", 30, 6, true]
},
"fer":{
"condition":["servicedata", 25, "9"],
"decoder":["value_from_hex_data", "servicedata", 30, 4, true]
}
}
})"""",
```

Each device must provide a `brand`, `model`, `model_id`, `condition`, and `properties`.
- `brand` = brand name of the device.
- `model` = model name of the device.
- `model_id` = model id number of the device.

### Condition
`condition` is a JSON array, which must contain as the first parameter, the data source to test for the condtion. Valid inputs are:
- "servicedata"
- "manufacturerdata"
- "name"
- "uuid"

The second parameter is how the data should be tested. Valid inputs are:
- "contain" tests if the specified value (see below) exists the data source
- "index" tests if the specified value exists at the index location (see below) in the data source

The third parameter can be either the index value or the data value to find. If the second parameter is `contain`, the third parameter should be the value to look for in the data source. If the second parameter is `index`, the third parameter should be the location in the data source to look for the value provided as the fourth parameter.

`condition` can have multiple conditions chanined together using '|' and '&' between them.
For example: `"condition":["servicedata", "index", 0, "0804", '|', "servicedata", "index", 0, "8804"]`
This will match if the service data at index 0 is "0804" `OR` "8804".

### Properties
Properties is a nested JSON object containing one or more JSON objects. In the example above it looks like:
```
"properties":{
"tempc":{
"condition":["servicedata", 25, "4"],
"decoder":["value_from_hex_data", "servicedata", 30, 4, true],
"post_proc":['/', 10]
},
```

Here we have a single property that defines a value that we want to decode. The key "tempc" will be used as the key in the JsonObject provided when `decodeBLEJson(JsonObject)` is called. "tempc" in this example is another JSON object that has an (optional, explained below) `condition`, `decoder`, and `post_proc`.

`condition` is a JSON array. The first parameter defines the data source of the condition to test and must be one of:
- "servicedata"
- "manufacturerdata"

The second parameter is the index of the data source to look for the value. The third parameter is the value to test for.
If the condition is met the data will be decoded and added to the JsonObject.

`decoder` is a JSON array that specifies the decoder function and parameters to decode the value. The first parameter is the name of the function to call, currently only "value_from_hex_data" is valid. The other parameters are:
- "servicedata", Extract the value from the service data. Could also be "manufacturerdata"
- 30, The index of the data source where the value exists.
- 4, The length of the data in bytes (characters in the string).
- true/false, If the value in the data source should have it's endianness reversed before converting.
- (optional)true/false, Sets if the resulting value can be a negative number.

`post_proc` This specifies any post processing of the resulting decoded value. This is a JSON array that should be written in the order that the operation order is desired. In the simple example the first parameter is the '/' divide operation and the second parameter (10) is the value to divide the result by. Multiple operations can be chained together in this array to perform more complex calculations. Valid operations are:
- '/' divide
- '*' multiply
- '+' add
- '-' subtract
- '<' shift left
- '>' shift right
- '!' Not (invert), useful for bool types

`val_bits` (Not shown in the example) is an additional parameter that can be added to define the value. It will convert the post processed result into a value with the number of bits specified by `val_bits`. Valid values are: 1 (for bool), 8, 16, 32. Double is the default type if this is omitted.
1 change: 1 addition & 0 deletions src/arduino_json
Submodule arduino_json added at b81083
Loading

0 comments on commit 7b5b44e

Please sign in to comment.