Skip to content

Commit

Permalink
add support of sub unit, tariff and storage number
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeppelin500 committed Dec 12, 2023
1 parent c73705a commit da52bab
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 39 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [0.5.0] - 2023-12-12

### Added

- support sub unit, tariff and storage number

### Changed

- send only important and existing values to the json to save storage

## [0.4.0] - 2023-12-12

### Added
Expand Down
9 changes: 1 addition & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MBusinoLib - an Arduino M-Bus Decoder Library

[![version](https://img.shields.io/badge/version-0.4.0-brightgreen.svg)](CHANGELOG.md)
[![version](https://img.shields.io/badge/version-0.5.0-brightgreen.svg)](CHANGELOG.md)
[![license](https://img.shields.io/badge/license-GPL--3.0-orange.svg)](LICENSE)


Expand Down Expand Up @@ -52,11 +52,6 @@ Example JSON output:
```
[
{
"vif": 101,
"code": 21,
"scalar": -2,
"ascii": 0,
"value_raw": 2206,
"value_scaled": 22.06,
"units": "C",
"name": "external_temperature_min"
Expand All @@ -68,10 +63,8 @@ Example extract the JSON

```c
for (uint8_t i=0; i<fields; i++) {
uint8_t code = root[i]["code"].as<int>();
const char* name = root[i]["name"];
const char* units = root[i]["units"];
uint8_t ascii = root[i]["ascii"].as<int>(); //0 = double, 1 = ASCII, 2 = both;
double value = root[i]["value_scaled"].as<double>();
const char* valueString = root[i]["value_string"];

Expand Down
35 changes: 26 additions & 9 deletions examples/MBusino_naked/MBusino_naked.ino
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/*
# MBusino_naked --> only M-Bus capabilities
# MBusino_naked --> only M-Bus
21 October 2023: new code based at MBusino with payload library. You find the old "Sensostar only" code in archive.
documentation see Zeppelin500/MBusino
documentation see MBusino
## Licence
****************************************************
Expand All @@ -19,6 +20,7 @@ You should have received a copy of the GNU General Public License along with thi

#include <MBusinoLib.h> // Library for decode M-Bus
#include "ArduinoJson.h"
#include <EEPROM.h>

#define MBUSINO_NAME "MBusino" // If you have more MBusinos, rename it inside quote marks, or it cause some network and MQTT problems. Also you cant reach your MBusino from Arduino IDE

Expand Down Expand Up @@ -54,6 +56,11 @@ unsigned long timerMbus = 0;
void mbus_request_data(byte address);
void mbus_short_frame(byte address, byte C_field);
bool mbus_get_response(byte *pdata, unsigned char len_pdata);
void calibrationAverage();
void calibrationSensor(uint8_t sensor);
void calibrationValue(float value);
void calibrationBME();
void calibrationSet0();

void setup() {
Serial.begin(2400, SERIAL_8E1);
Expand All @@ -69,15 +76,15 @@ void setup() {
// This function is called once everything is connected (Wifi and MQTT)
// WARNING : YOU MUST IMPLEMENT IT IF YOU USE EspMQTTClient
void onConnectionEstablished() { // send a message to MQTT broker if connected.
client.publish(MBUSINO_NAME"/start", "bin hoch gefahren, WLAN und MQTT steht ");
client.publish(MBUSINO_NAME"/start", "bin hoch gefahren, WLAN und MQTT seht ");
}

void loop() {
client.loop(); //MQTT Funktion
loop_start = millis();


if ((loop_start-last_loop)>= MbusInterval || firstrun) { // 9800 = ~10 seconds
if ((loop_start-last_loop)>= MbusInterval || firstrun) {
last_loop = loop_start; firstrun = false;

bool mbus_good_frame = false;
Expand Down Expand Up @@ -106,17 +113,27 @@ void loop() {


for (uint8_t i=0; i<fields; i++) {
double value = root[i]["value_scaled"].as<double>();
uint8_t code = root[i]["code"].as<int>();
const char* name = root[i]["name"];
const char* units = root[i]["units"];
const char* units = root[i]["units"];
double value = root[i]["value_scaled"].as<double>();
const char* valueString = root[i]["value_string"];

//two messages per value
client.publish(String(MBUSINO_NAME"/MBus/"+String(i+1)+"_"+String(name)), String(value,3).c_str());
//two messages per value, values comes as number or as ASCII string or both
client.publish(String(MBUSINO_NAME"/MBus/"+String(i+1)+"_vs_"+String(name)), valueString); // send the value if a ascii value is aviable (variable length)
client.publish(String(MBUSINO_NAME"/MBus/"+String(i+1)+"_"+String(name)), String(value,3).c_str()); // send the value if a real value is aviable (standard)
client.publish(String(MBUSINO_NAME"/MBus/"+String(i+1)+"_"+String(name)+"_unit"), units);
//or only one message
//client.publish(String(MBUSINO_NAME"/MBus/"+String(i+1)+"_"+String(name)+"_in_"+String(units)), String(value,3).c_str());



if (i == 3){ // Sensostar Bugfix --> comment it out if you use not a Sensostar
float flow = root[5]["value_scaled"].as<float>();
float delta = root[9]["value_scaled"].as<float>();
float calc_power = delta * flow * 1163;
client.publish(MBUSINO_NAME"/MBus/4_power_calc", String(calc_power).c_str());
}

}

}
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"type": "git",
"url": "https://github.com/Zeppelin500/MBusinoLib.git"
},
"version": "0.4.0",
"version": "0.5.0",
"license": "GPL-3.0",
"frameworks": "arduino",
"platforms": ["atmelavr", "atmelsam", "espressif8266"],
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=MBusinoLib
version=0.4.0
version=0.5.0
author=Zeppelin500 <[email protected]>
maintainer=Zeppelin500 <[email protected]>
sentence=an Arduino M-Bus decode Library
Expand Down
77 changes: 57 additions & 20 deletions src/MBusinoLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,34 @@ uint8_t MBusinoLib::decode(uint8_t *buffer, uint8_t size, JsonArray& root) {


// handle DIFE to prevent stumble if a DIFE is used
bool dife = ((dif & 0x80) == 0x80); //check if the first bit of DIF marked as "DIFE is following"
while(dife) {
uint16_t storageNumber = 0;
if((dif & 0x40) == 0x40){
storageNumber = 1;
}
uint8_t difeNumber = 0;
uint8_t dife[10] = {0};
bool ifDife = ((dif & 0x80) == 0x80); //check if the first bit of DIF marked as "DIFE is following"
while(ifDife) {
difeNumber ++;
dife[difeNumber] = buffer[index];
ifDife = false;
ifDife = ((buffer[index] & 0x80) == 0x80); //check if after the DIFE another DIFE is following
index++;
dife = false;
dife = ((buffer[index-1] & 0x80) == 0x80); //check if after the DIFE another DIFE is following
}
uint8_t subUnit = 0;
uint8_t tariff = 0;

for(uint8_t i = 0; difeNumber > 0 && i<=difeNumber; i++){
if(i==0){
storageNumber = storageNumber | ((dife[i+1] & 0x0F) << 1);
}
else{
storageNumber = storageNumber | ((dife[i+1] & 0x0F) << (4*i));
}
subUnit = subUnit | (((dife[i+1] & 0x40) >> 6) << i);
tariff = tariff | (((dife[i+1] & 0x30) >> 4) << (2*i));
}

// End of DIFE handling


Expand Down Expand Up @@ -242,7 +264,6 @@ uint8_t MBusinoLib::decode(uint8_t *buffer, uint8_t size, JsonArray& root) {
uint8_t date[len] ={0};
char datestring[12] = {0}; //needed for simple formatted dates
char datestring2[24] = {0};//needed for extensive formatted dates
int out_len = 0;
char valueString [12] = {0}; // contain the ASCII value at variable length ascii values and formatted dates
bool switchAgain = false; // repeat the switch(dataCodingType) at variable length coding
bool negative = false; // set a negative flag for negate the value
Expand Down Expand Up @@ -369,20 +390,20 @@ uint8_t MBusinoLib::decode(uint8_t *buffer, uint8_t size, JsonArray& root) {
//out_len = snprintf(output, output_size, "invalid");
break;
}
out_len = snprintf(datestring, 24, "%02d%02d%02d%02d%02d",
snprintf(datestring, 24, "%02d%02d%02d%02d%02d",
((date[2] & 0xE0) >> 5) | ((date[3] & 0xF0) >> 1), // year
date[3] & 0x0F, // mon
date[2] & 0x1F, // mday
date[1] & 0x1F, // hour
date[0] & 0x3F // sec
date[0] & 0x3F // min
);

out_len = snprintf(datestring2, 24, "%02d-%02d-%02dT%02d:%02d:00",
snprintf(datestring2, 24, "%02d-%02d-%02dT%02d:%02d",
((date[2] & 0xE0) >> 5) | ((date[3] & 0xF0) >> 1), // year
date[3] & 0x0F, // mon
date[2] & 0x1F, // mday
date[1] & 0x1F, // hour
date[0] & 0x3F // sec
date[0] & 0x3F // min
);
value = atof( datestring);
strcpy(valueString, datestring2);
Expand All @@ -397,12 +418,12 @@ uint8_t MBusinoLib::decode(uint8_t *buffer, uint8_t size, JsonArray& root) {
//out_len = snprintf(output, output_size, "invalid");
break;
}
out_len = snprintf(datestring, 10, "%02d%02d%02d",
snprintf(datestring, 10, "%02d%02d%02d",
((date[0] & 0xE0) >> 5) | ((date[1] & 0xF0) >> 1), // year
date[1] & 0x0F, // mon
date[0] & 0x1F // mday
);
out_len = snprintf(datestring2, 10, "%02d-%02d-%02d",
snprintf(datestring2, 10, "%02d-%02d-%02d",
((date[0] & 0xE0) >> 5) | ((date[1] & 0xF0) >> 1), // year
date[1] & 0x0F, // mon
date[0] & 0x1F // mday
Expand Down Expand Up @@ -432,24 +453,40 @@ uint8_t MBusinoLib::decode(uint8_t *buffer, uint8_t size, JsonArray& root) {

// Init object
JsonObject data = root.createNestedObject();
data["vif"] = vif;
data["code"] = vif_defs[def].code;
data["ascii"] = asciiValue; //0 = double, 1 = ASCII, 2 = both;
if(asciiValue != 1){
data["scalar"] = scalar;
data["value_raw"] = value;
//data["vif"] = String("0x" + String(vif,HEX));
//data["code"] = vif_defs[def].code;

if(asciiValue != 1){ //0 = double, 1 = ASCII, 2 = both;
//data["scalar"] = scalar;
//data["value_raw"] = value;
data["value_scaled"] = scaled;
}
if(asciiValue > 0){
if(asciiValue > 0){ //0 = double, 1 = ASCII, 2 = both;
data["value_string"] = String(valueString);
}
if(ifcustomVIF == true){
data["units"] = String(customVIF);
}
else{
else if(getCodeUnits(vif_defs[def].code)!=0){
data["units"] = String(getCodeUnits(vif_defs[def].code));
}
data["name"] = String(getCodeName(vif_defs[def].code)+String(stringFunctionField));
if(subUnit > 0){
data["subUnit"] = subUnit;
}
if(storageNumber > 0){
data["storage"] = storageNumber;
}
if(tariff > 0){
data["tariff"] = tariff;
}
/* // only for debug
data["difes"] = difeNumber;
if(difeNumber > 0){
data["dife1"] = dife[1];
data["dife2"] = dife[2];
}
*/
if(buffer[index] == 0x0F ||buffer[index] == 0x1F){ // If last byte 1F/0F --> More records follow in next telegram
index++;
}
Expand Down Expand Up @@ -569,7 +606,7 @@ const char * MBusinoLib::getCodeUnits(uint8_t code) {

}

return "";
return 0;

}

Expand Down

0 comments on commit da52bab

Please sign in to comment.