Giter Site home page Giter Site logo

bertmelis / vitowifi Goto Github PK

View Code? Open in Web Editor NEW
116.0 18.0 39.0 1.18 MB

Communicate with Viessmann boilers using the optolink for ESP8266 and ESP32

License: MIT License

Batchfile 0.89% C 2.17% C++ 96.94%
esp8266 esp8266-arduino serial communication viessmann optolink iot esp32 heating heating-control

vitowifi's Introduction

VitoWiFi



ATTENTION

Version 1 (current master branch) and version 2 will be deprecated soon. I'm working on v3 of this library which will be simpler, more versatile and more compact. You can follow development in the v3 branch.



Build Status Gitter chat

Arduino Library for ESP8266 to communicate with Viessmann boilers using a (DIY) serial optolink.

Based on the fantastic work on openv. Check out this wiki for a simple hardware implementations

This library is non-blocking This also means that the use of blocking code is not supported. Since we're talking serial @4800 baud, we would be wasting precious processing time while reading and writing to the optolink. Furthermore this library is useable in async or non blocking frameworks such as the marvellous Homie for esp8266 framework or Blynk.

Table of contents

Prerequisites

  • Platformio or Arduino for ESP8266
  • a (DIY) serial optocoupler to connect your ESP8266 to your Viessmann boiler
  • As this is an implementation of the P300 (aka VS2) and KW protocol, your boiler must be compatible with these protocols.

Installation

Steps to get going

Define the protocol

VitoWiFi_setProtocol(protocol);  // set protocol to KW or P300

There’s no typo! This line calls a macro that initialises the class with the protocol parameter: VitoWiFi is a templated class where the template parameter is the protocol. The template design avoids a virtual function call on every interaction with the optolink interface.
Also, don't use quotes, protocol is an enum.

Define your datapoints

DPTemp myTempDP(const char name, const char group, uint16_t address)

There are a number of predefined datapoint types:

  • DPTemp: 2 byte, factor 10, returning float
  • DPTempS: 1 byte, no factor, returning uint8_t
  • DPStat: 1 byte, no factor, returning bool
  • DPCount: 4 byte, no factor, returning uint32_t
  • DPCountS: 2 byte, no factor, returning uint16_t
  • DPMode: 1 byte, node mode, return uint8_t (same as DPTempS)
  • DPHours: 4 byte, factor 3600, returning float
  • DPCoP: 1 byte, factor 10, returning float
  • DPRaw (see datapoints)

Each datapoint is defined by a name, a group and an address. The addresses notation is mostly in a 2-byte hex eg. 0x5525.

Read on about datapoints in the separate chapter about datapoints.

Setup VitoWiFi

In void setup()

VitoWiFi.setup(&Serial);

Assign the serial interface connected to the optolink. Pass by reference. For ESP32 you also have to give the two pin numbers: setup(&Serial, 21, 22). The serial interface will be set to 4800 baud, 8 bits, even parity and 2 stop bits by vitoWiFi.

VitoWiFi.setGlobalCallback(Callback);

Set the function to execute when data is received when there is no callback defined for the currently processed datapoint. The callback has the following signature: void function(IDatapoint*, DPValue)

Set additional properties of the individual datapoints:

  • IDatapoint.setWriteable(bool) to make to datapoint R/W instead or RO by default
  • IDatapoint.setCallback(Callback) to assign a custom, per datapoint, callback handler. The signature is the same.

The modifiers can be chained, they return a reference to the datapoint.

Optionally:

  • VitoWiFi.setLogger(Printer*) so vitoWiFi can print messages for debugging purposes.
  • VitoWiFi.enableLogger() or .disableLogger() enables or disables logging

In void loop()

Call VitoWiFi.loop(); in the Arduino void loop(). Avoid blocking code. Minimize lengthy calculations etc. VitoWiFi will probably still work (the amount of data coming from the optolink is limited) but vitoWiFi works by polling so try to poll as much as possible.

Read/write datapoints

VitoWiFi.readDatapoint(IDatapoint&);

You pass the datapoints you created in step 1. The datapoint is passed by reference.
Do not call this repeatedly but use a timed call. On every call, the action is placed in a queue. This queue is limited in size.
Mind that it takes some time (although less than 10ms) to process an action so calling too often will fill the queue.

VitoWiFi.writeDatapoint(IDatapoint&, DPValue);

The same as readDatapoint but with an extra DPValue parameter holding the value to be written. Make sure to initialize the value correctly. More on this in the chapter DPValue.

Alternative ways to read datapoints is by calling

  • VitoWiFi.readAll();
  • VitoWiFi.readGroup(const char*);

You cannot write to multiple datapoints in one command.

Datapoints

Some insights...
The datapoints architecture is as follows: there is an "IDatapoint" class which is the superclass from which all datapoint types inherit. The is done to have a base type (pointer) for universal storage of the datapoints in a std::vector.
A templated "Datapoint" class inherits from "IDatapoint". "Datapoint" contains a class member, which is the template parameter, that handles the encoding and decoding.
For easier coding, the builtin specialized classed have a typedef.

An overview of the builtin datapoint types:

Type Underlying type Length Conversion factor Value type
DPTemp Datapoint<conv2_10_F> 2 / 10 float
DPTempS Datapoint<conv1_1_US> 1 1 uint8_t
DPStat Datapoint<conv1_1_B> 1 1 uint8_t
DPCount Datapoint<conv4_1_UL> 4 1 uint32_t
DPCountS Datapoint<conv2_1_UL> 2 1 uint16_t
DPMode Datapoint<conv1_1_US> 1 1 uint8_t
DPHours Datapoint<conv4_3600_F> 4 / 3600 float
DPCoP Datapoint<conv1_10_F> 1 / 10 float
DPRaw Datapoint -(1) - uint8_t*

(1) the length of DPRaw has to be explicitly set using setLength()

My datapoint type isn’t listed?

Then you can build it yourself! (and make a PR afterwards) But how do I do this?

Below is an example that creates a type called "DPSeconds" for a 4 bytes datapoint that holds a seconds counter. The datapoint converts this to a float with the number of minutes. You can place this directly in your code or place it in a seperate file that you include. If you use a seperate file, make sure you include "Datapoint.hpp" in that one.

// first create a converter class, and inherit from DPType
class conv4_60_F : public DPType {
 public:
  void encode(uint8_t* out, DPValue in) {  // encode can be left empty when the DP is only used for reading.
  int32_t tmp = floor((in.getFloat() * 60) + 0.5);
  out[3] = tmp >> 24;
  out[2] = tmp >> 16;
  out[1] = tmp >> 8;
  out[0] = tmp & 0xFF;
  }
  DPValue decode(const uint8_t* in) {
    int32_t tmp = in[3] << 24 | in[2] << 16 | in[1] << 8 | in[0];  // keep endianess in mind! input is LSB first
    DPValue out(tmp / 60.0f);
    return out;
  }
  const size_t getLength() const {
    return 4;
  }
};
// the typedef is optional. If you should consider making a PR,
// please do make a typedef for consistency.
typedef Datapoint<conv4_1_UL> DPMinutes;

// now you can use the newly created type:
DPMinutes myDatapoint("name", "group", 0x1234);

The example above is also in the examples folder.

DPValue

DPValue is a structure that is used as a universal data holder. It can hold a bool, a unsigned integers (8, 16 and 32 bit) or a float. It cannot convert between types although a getString() method is available to print our it’s value. An example:

uint16_t myInt = 234;
DPValue value(234);  // value holds a uint16_t with value 234
value1 = value.getFloat();  // value1 = 0 as value didn’t contain a float
value1 = value.getU16()  // value1 = 234
char str[4];
value.getString(str, sizeof(str));  // str contains “234” (+ extra null-termination)

The possible types are:

type getter prints
uint8_t getU8() %u
uint16_t getU16() %u
uint32_t getU32() %u
bool getBool() "true" or "false"
float getFloat() %.1f
raw getRaw(uint8_t*) %02x

Optolink

The optolink is the core of this library. It is rather unpolished and requires some insights to use on it’s own. Please refer to the example for more details. There are 2 versions: one for the KW protocol and one for the P300 protocol. Both work as a finite state machine with sequential connection management, waiting state, polling for a response and returning to idle.

You should first try if the P300 protocol works and if it doesn’t, try KW. If that also doesn’t work, you have a hardware problem or an unsupported boiler. When making bug reports, make sure to include hardware details.

End note

Examples

Next to the examples in this repo, you can find the firmware of the setup I'm using in this repo: esp8266-heating.

History

I was using the original openv/vcontrold code from wikispaces on a Raspberry Pi V1. However, this setup was a bit overkill: such a powerful device doing only serial communication at 4800 baud. So I wanted to optimise this situation. An ESP8266 has built-in serial/UART communication and is obviously connectable via Wifi. The small form factor and power consumption were bonus points. Ever since it has been made compatible with the Arduino environment (or other way around), it is my Nr 1 choice for IoT applications.

License

Copyright (c) 2017 Bert Melis

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Credits go to

  • Hex print: 2011, robtillaart @ Arduino.cc forum
  • Logger/Blinker: MIT 2015, marvinroger @ Github
  • Serial Protocol @ openv.wikispaces.com
  • tolw for implementing the writing
  • Empor-co for testing the KW-protocol
  • and many others for code and inspiration

vitowifi's People

Contributors

bertmelis avatar empty88 avatar tolw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vitowifi's Issues

ack followed by nack timeout.

just tried your new version 1.0 on my WO1B/Vitocal300
Based on your raw example I tried data points 0x5525, 0x810 and 0x812.
None of them was on my list before, so I don't know if they work.
Odd thing, however, is that 0x5525 gives a ack nack timeout reply.

READ 4105000155250282
ack
nack, timeout
1
READ 4105000108100220
ack
RCV 41070101081002000023
ack
Address 810 has value 0000FE
READ 4105000108120222
ack
RCV 41070101081202000025
ack
Address 812 has value 0000FE

"Listen only" mode

Dear Bert,
thanks a ton for your effort and this project!

I currently have a Vitoconnect connected to my heating control unit. Now I like to add a DIY adapter to the OPTOLINK interface to make the heating data available to my home automation system (it is ridiculous, that Viessmann is not planning to provide a public API for their Vitoconnect >:( ).

To not disturb/the "normal" communication between Vitoconnect and the control unit, I like to firstly analyze the communication between both.

  • what is send/requested by the Vitoconnect
  • what are the answers of the control unit
  • what is the timing/intervals of communication between both

With the knowledge about these things, I could decide, if it is necessary to transmit/request data by myself, or if it is sufficient to just process the data, that is requested by the Vitoconnect anyway.

Now the question: can I use your software for the ESP8266 to just listen to the communication that is going on? I would define the protocol, and then the software should just process all incoming data and decode it according to the defined protocol.

What do you think about this approach?

Thanks and greetings

Add and rearrange datapoints

see PR #8

Idea is to create a number of base DPs and subDPs. Whenever there are subDPs, the base is an abstract one.
TempBase --> TempDP (2-byte / 10) and TempSDP (1-byte)
CountBase --> (have to make the inventory)
ModeDP (no subDPs?)
...

8 Byte read extension with uint64_t brings inconsistent results

Installation specifics
Heating type: Vitotronic 200 KW2
Protocol: KW
Board: ESP8266 Wemos D1 mini
Hardware: own IR components
Symptom

I extended with an 8 Byte part for reading RAW-data "System Time" and the "on/off timer" from the different days of e.g. "Zirkulationspumpe"
code changes are at the end listed.

in the main program I used with additional related changes:

DP8Timer getAnlagenzeit("getanlagenzeit", "allgemein", **0x088E**);   //Anlagenzeit  0x088E 
DP8Timer getTimerZirkuSa("gettimerzirkusa", "allgemein", **0x2228**);   //Zirkulationspumpe Zeiten Samstag

Only the address is different.
But on MQTT I get back:
gettimerzirkusa = FFFFFFFF94803B30
getanlagenzeit = 2092220

Is there anyone who can give an explanation for this. Both should deliver 8 Bytes result?!

DPTypes.cpp:

void conv8Timer::encode(uint8_t* out, DPValue in) {
//zum Schreiben
  uint64_t tmp = in.getU64();
  out[7] = tmp >> 56;
  out[6] = tmp >> 48;
  out[5] = tmp >> 40;
  out[4] = tmp >> 32;
  out[3] = tmp >> 24;
  out[2] = tmp >> 16;
  out[1] = tmp >> 8;
  out[0] = tmp & 0xFF;

}
DPValue conv8Timer::decode(const uint8_t* in) {
//zum Lesen
  uint64_t tmp = in[7] << 56 | in[6] << 48 | in[5] << 40 | in[4] << 32 | in[3] << 24 | in[2] << 16 | in[1] << 8 | in[0];
  DPValue out(tmp);
  return out;
}

DPTypes.hpp

class conv8Timer : public DPType {
 public:
  void encode(uint8_t* out, DPValue in);
  DPValue decode(const uint8_t* in);
  const size_t getLength() const { return 8; }
}; 

Datapoint.hpp

typedef Datapoint<conv8Timer> DP8Timer;

crash after several hours

VitoWifi crashes after several hours.
possible memory overrun?

Firmware with VitoWifi, Homie and WifiPrinter.

Enhancement to Wifi-commands

You call the (great) project VitoWiFi. Does WiFi stand for wireless? In this case I was wondering whether you included some Wifi-Code so that Vito data can be read and written over the internet. Do you have any code to do this?

(Or is this something that someone, whoever that is ;-) , has to do?)

Feature request: Software serial

I know, there is nothing like a UART. But since the ESP8266 only has one developing with it is... tricky.
The same pins are used for communicating with Vito, for debug and programming.

The Vitostuff does communicate so slow that a software serial would be a real option. And the Vito connection could be moved somewhere else.

Alternative: Serial.swap() to use TX2/RX2. You can swap at run-time and I 've seen programs doing that frequently just for debug. Just mind to flush() before swapping.

VitoWifi ESP8266 with Blynk

Installation specifics

  • Heating type: Vitoladens 300 with Vitotronic 200 KW2
  • Protocol: KW
  • Board: ESP8266
  • Hardware: TBD

VitoWifi ESP8266 with Blynk

This thread is to follow the evolution of a project I want to realise, that is be able to monitor
my heater remotely with Blynk https://www.blynk.cc/
Bert, If you dont mind, I will ask here all the necessary questions for the implementation of my project and provide the details of its evolution.

First questions :

I see in your example

VitoWifi.addDatapoint("outsidetemp", "boiler", 0x5525, TEMP);
VitoWifi.addDatapoint("boilertemp", "boiler", 0x0810, TEMP);
But it is not clear to me where is the table of all adresses for the different functions ?
for the KW protocol.

I would have expect to see a file with all this information, and I dont find it. DO you have it ?

Thanks

Read/Write buffer: fixed size

Installation specifics

  • Heating type: Vitotronic 200
  • Protocol: KW
  • Board: ESP8266

Symptom

Reading/Writing Datapoint KW with length > 4 does not work.

Extra info

First of all: Outstanding work!

I set MAX_DP_LENGTH to 8 to read 'cycle time' datapoints (DPRaw) with length 8, but got weird return values.
After digging into the code i figured out read/write buffers are limited to 4/6 bytes.
But i'm not an expert, so please have a look at my hack! :)

diff.txt

KW runs into Timeout

Installation specifics

  • Protocol: KW
  • Board: ESP8266 as well as ESP32, both adafruit feather

Symptom

Values are not read correctly. It sometimes workes nicely but degrades suddenly. I can see Readall being called but the handles not involved. If values are returned they are mostly bogous like temperature being 128.5 C. After uncommenting in the header file the debugging I do see the following:

READ outsideTemp READ boilertemp READ pump TestOptolink action: 1 Optolink state: 2 Optolink state: 3 Optolink state: 4 READ 5525 timeout Optolink state: 0 Optolink action: 3 Optolink action: 0 DP outsideTemp error: 1 Optolink action: 1 Optolink state: 1 Optolink state: 2 Optolink state: 3 Optolink state: 4 READ 0810 timeout Optolink state: 0 Optolink action: 3 Optolink action: 0 DP boilertemp error: 1 Optolink action: 1 Optolink state: 1 Optolink state: 2 Optolink state: 3 Optolink state: 4 READ 2906 timeout Optolink state: 0 Optolink action: 3 Optolink action: 0 DP pump error: 1 Optolink state: 1
When I blindly "fire" some requests directly to the serial I do get the right values returned.

Any ideas?

Thank you in advance,

empor

Platform independent library

Hi,
Is there any possibility to make the code independent from hardware platform (ESP chip)? I am about to built system based on Arduinos as let me say protocol converters and RPi with Domotics as user facing gateway connected to Vitocal 200s via Optolink and Vitosolic 200 via vbus to be able to monitor and configure whole system remotely. I prefer to use wired solution instead of WiFi (because of security, availability and stability). In fact from my point of view there is no dependency to WiFi and ESP chip and to have the the library platform independent is not bad idea in my opinion.

I have made some changes in source code and have tried to compile it for Arduino Nano board but have no success. Honestly speaking unfortunately I am not so good in C++ :-(.

Thank you

"Betriebsart" as example delivers always "0"

Installation specifics

  • Heating type: Vitotronic 200 KW2
  • Protocol: KW
  • Board: ESP8266 Wemos D1 mini
  • Hardware: own IR components

Symptom

What happens? some values do not work

example:
DPMode getBetriebArtM1("getbetriebartm1","betriebsarten", 0x2301); //HK1 0=Abschaltb,1=nur WW,2=heiz+WW, 3=DauernRed,3=Dauer Norma.

I also tried address 2500 and 2501, but always a "0" is delivered on the MQTT interface.
Normally now I expect a "1" for only WW

Is the Address wrong or the coding?

Thanks

Errors on high MQTT request rate

Installation specifics
Heating type: Vitotronic 200 KW2
Protocol: KW
Board: ESP8266 Wemos D1 mini
Hardware: own IR components

Issue: errors on high MQTT request rate

I used the new common developed [;-)] conv8_1_Timer for the setting of the weekday on/off timing of heating, water and circulation pump.
If I set the 4 periods for a single week day all is working (one 8 Byte command)
If I send 5 commands (Monday-Friday) from NodeRed with MQTT directly to VitoWifi, only Monday is correct and the others contain "FFFFFFFFFFFFFFFF". This is also seen in the Debug WRITE output from VitoWifi.
If I put 1 second delay in NodeRed between each weekday setting command, all is working.

I expected a queued handling of the set commands without errors.

Any idea?

Feature request: value factor

Some datapoints require applying a factor to the reading. How about adding that factor to
VitoWifi.addDatapoint(..., factor) so that the globalCallbackHandler has that factor or the correct value available ?

Exception29 when interface is disconnected

it was all running smoothly until I disconnected the cable and forgot to re-connect it. After a while it crashed. Looks like a simple queue overflow to me ;-)
I had 60 datapoints queried at an interval of 10s, so the queue was filling up pretty quick.
I suggest to limit the queue size to the amount of added data points.


Exception (29):
epc1=0x40203e29 epc2=0x00000000 epc3=0x00000000 excvaddr=0x0000000c depc=0x00000000

ctx: cont 
sp: 3fff02e0 end: 3fff0560 offset: 01a0

>>>stack>>>
3fff0480:  3ffef4e0 000002d6 3fff04ae 40205c31  
3fff0490:  00000002 00000001 3ffe9288 402066bc  
3fff04a0:  00000000 00000001 3ffe9288 402066bc  
3fff04b0:  3fff0510 0000002a 3ffe8d58 3ffef52c  
3fff04c0:  3fff20f8 0000002b 3ffef4e4 40205b1d  
3fff04d0:  3ffe9287 3fff1e2c 3ffef4e4 40205b1d  
3fff04e0:  3ffe8d2e 3ffef088 3ffef4e4 40205b48  
3fff04f0:  00000000 4bc6a7f0 3ffef4e4 3ffef52c  
3fff0500:  3fff20f8 3fff1e44 3ffef07c 40203f57  
3fff0510:  3fff1e44 00000000 00000000 6353f7ce  
3fff0520:  00000000 3ffef07c 3fff20ac 40203f99  
3fff0530:  3fffdad0 3ffef078 3ffef07c 40202ec0  
3fff0540:  3fffdad0 00000000 3ffef524 40206190  
3fff0550:  feefeffe feefeffe 3ffef540 40100739  
<<<stack<<<

last failed alloc call: 40203F00(504)

 ets Jan  8 2013,rst cause:4, boot mode:(1,6)

wdt reset

Exception decoder says:

Exception 29: StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores
Decoding 12 results
0x40203e29: construct  at /home/john/Arduino/scetchbooks/libraries/VitoWifi/VitoWifi.cpp line 274
:  (inlined by) std::deque   >::push_back(VitoWifiBase::Action const&) at /home/john/Arduino/github/Core/Arduino/tools/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/bits/stl_deque.h line 1395
0x40205c31: Print::printNumber(unsigned long, unsigned char) at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp line 92
0x402066bc: Print::write(unsigned char const*, unsigned int) at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp line 92
0x402066bc: Print::write(unsigned char const*, unsigned int) at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp line 92
0x40205b1d: Print::write(char const*) at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp line 92
0x40205b1d: Print::write(char const*) at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp line 92
0x40205b48: Print::println() at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp line 92
0x40203f57: VitoWifiBase::_readDatapoint(Datapoint*) at /home/john/Arduino/scetchbooks/libraries/VitoWifi/VitoWifi.cpp line 274
0x40203f99: VitoWifiBase::readAll() at /home/john/Arduino/scetchbooks/libraries/VitoWifi/VitoWifi.cpp line 274
0x40202ec0: loop at /home/john/Arduino/scetchbooks/reaDatatpoint/readDatapoint/readDatapoint.ino line 175
0x40206190: loop_wrapper at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 58
0x40100739: cont_wrapper at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/cont.S line 81

Please tell me the request address V100 boiler pump in operation or not / It is not in the list of addresses of Viessmann-adresses

Installation specifics

  • Heating type: eg. 20CB - Vitodens 200 with Vitotronic 200
  • Protocol: KW or P300
  • Board: ESP8266 or ESP32 (others?), possible brand/make (NodeMCU, Wemos D1 mini...)
  • Hardware: Which hardware implementation did you use?

Symptom

What happens? (crash, unresponsive, nothing at all...)
When does it happen? (after several hours, immideately...)
What would you expect?
...

Be as complete as you can!

Extra info

Please add relevant debug information like debug messages, (decoded) stack traces...

You don't have to provide all the info, but less is not always more!

interface with Open Energy Monitor

Installation specifics

  • Heating type: Vitodens 200 i think
  • Protocol: unknown
  • Board: nothing yet
  • Hardware:

Viessmann 222f boiler.

We have the above unit and I understand the hardware side of an esp. we have a home energy monitoring system https://openenergymonitor.org/ i am wondering if it would be possible for your code to be modified to output to emoncms, I have very little programing skills but a lot of enthusiasm.

https://github.com/emoncms/emoncms Main emoncms info
https://github.com/emoncms/emoncms/blob/master/Modules/input/Views/input_api.php Input API

They already use esp8266 in some of there products.
https://github.com/OpenEVSE/ESP8266_WiFi_v2.x

VitoWiFi.readDatapoint() only on MQTT request

Installation specifics
Heating type: Vitotronic 200 KW2
Protocol: KW
Board: ESP8266 Wemos D1 mini
Hardware: own IR components

Question:
I want a MQTT update not in a loop but for some values on request only. But it works not as expected?!

Example:
if i use below line with all related configurations, I get an MQTT: VITOWIFI/gettimerzirkusa with its value each minute.
getTimerZirkuSa.setCallback(DP8TimerCallbackHandler); //fuer Timer

then I added:
in the MQTT receiving part, for a new MQTT message "retrievetimerzirkusa" to get the DP "gettimerzirkusa" on request:

if (strcmp(topic, "VITOWIFI/retrievetimerzirkusa") == 0) {
  VitoWiFi.readDatapoint(getTimerZirkuSa);
}

and
mqttClient.subscribe("VITOWIFI/retrievetimerzirkusa", 0);

to get no updates per minute, I took out:
//getTimerZirkuSa.setCallback(DP8TimerCallbackHandler); //fuer Timer

What did I not understand?

Thanks.

ESP 8266 with Loxone SmartHome

Hi Bert, I want to control my Viessmann Vitodens 200 with Loxone. But there is no ready hardware and software. I have done many projects on NodeMCUs oder Arduinos. Is the ESP8266 library directly flashable? I want to receive UDP Messages from the NodeMCU with all the readings and I want to send UDP Messages to the NodeMCU with the new values to set. Is there any code for this application or how can I realise this?

Greets from Germany, Vincent.

Platformio build not possible [.pioenvs\esp8266\firmware.elf] Error 1

Software Tools used:
Windows 10
Atom 1.25.1
Platformio IDE Home 2.0.0·Core 3.6.4

I am not able to build the software. I tried the installed Atom / Platformio as well as a portable version.
The Error is with both build environments (ESP8266 and ESP32) the same:

collect2.exe: error: ld returned 1 exit status
*** [.pioenvs\esp8266\firmware.elf] Error 1

error log.txt

What I did so far:
I took the example from the esp8266-heating and copied the files platformio.ini and main.cpp into the relevant folders adapted everything as decribed and tried the build.
I have no idea how to proceed and debug further on. Guess it's a very common problem many of you faced with.
Can anybody provide a stable set to build the software with the VitoWifi-master repository? That would be the best way. Or at least point your finger into the direction I might find the problem.

image

Many thanks in advance!

For information: * Hardware: Which hardware implementation did you use?

Installation specifics

  • Heating type: Vitotronic 200 KW1
  • Protocol: KW
  • Board: ESP8266 or ESP32 (others?), possible brand/make (NodeMCU, Wemos D1 mini...)

Wrong logging output

based on your raw example, I set the data points struct to be:

const Datapoint Datapoints[] = {
    0x0101, 4,  // outside temp
    0x00F8, 2,  // HW Kennung
    0x0113, 4   // solar storage temp
};


Reading then returns:

READ 410500010101040c
ack
RCV 410901010101040a01e300ff
ack
Address 101 has value A1E30FE


READ 4105000100f80200
ack
RCV 4107010100f80220496c
ack
Address F8 has value 204900FE


READ 410500010113041e
ack
RCV 41090101011304b603bc029a
ack
Address 113 has value B63BC2FE

I spotted two issues:

  1. The value 0a01e300 is output as A1E30FE. It omits leading zeros of the single bytes and appends FE.

  2. The vaule 2049 is output as 204900FE even tough there were only two bytes data received. Appends FE

  3. The value b603bc02 is output as B63BC2FE. Same as 1.

DPCoP and group

Installation specifics
Heating type: Vitotronic 200 KW2
Protocol: KW
Board: ESP8266 Wemos D1 mini
Hardware: own IR components
Symptom

a) in the "Heizkennlinie Neigung" there is e.g. the value "0D" =13 or 1.3
with
DPTempS getNeigungA1M1("getneigunga1m1", "heizkreise", 0x2305)
I get the "13" in MQTT.

with
DPCoP getNeigungA1M1("getneigunga1m1", "heizkreise", 0x2305)
I expected "1.3" but a "0.00" is presented. Is this correct?

  • DPCoP: 1 byte, factor 10, returning float

b) group
above the group "heizkreise" or in
DPStat getBrennerStoerung("getbrennerstoerung", "allgemein", 0x0883)
"allgemein"
I still have not understood, for what this parameter is used. Can somebody explain me or give me a link, where I have overseen the explanation?!

Thanks

readDatapoint.ino crashes on ESP32

Hi,

I tried to run the example on a Adafruit HUZZAH32 – ESP32 Feather Board and switched Serial and Serial1 for better debugging.
Sadly the example keeps crashing when calling VitoWifi.loop(); in the loop.

Any ideas?

Thank you in advance.

Best regards,

E-co

Major flaw in protocol implementation

P300-protocol only!

I missed an update in the openv-wiki with a clarification of the comm protocol. VitoWifi should also send 0x06 when a correct telegram has been received, but it doesn't send anything.
The current workaround (which always has been implemented) is to resync.

I'll publish an update soon.

Linker error in Example readDatapoint: Logger

Installation specifics

  • Board: Wemos D1 mini.

Symptom

Linking everything together...
"/home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc" -g -w -Os -nostdlib -Wl,--no-check-sections -u call_user_start -u _printf_float -u _scanf_float -Wl,-static "-L/home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/tools/sdk/lib" "-L/home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/tools/sdk/ld" "-L/home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/tools/sdk/libc/xtensa-lx106-elf/lib" "-Teagle.flash.4m1m.ld" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read  -o "/tmp/arduino_build_6867/readDatapoint.ino.elf" -Wl,--start-group "/tmp/arduino_build_6867/sketch/readDatapoint.ino.cpp.o" "/tmp/arduino_build_6867/libraries/VitoWifi/Datapoint.cpp.o" "/tmp/arduino_build_6867/libraries/VitoWifi/OptolinkKW.cpp.o" "/tmp/arduino_build_6867/libraries/VitoWifi/OptolinkP300.cpp.o" "/tmp/arduino_build_6867/libraries/VitoWifi/VitoWifi.cpp.o" "/tmp/arduino_build_6867/arduino.ar" -lhal -lphy -lpp -lnet80211 -llwip2 -lwpa -lcrypto -lmain -lwps -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 -lstdc++ -lm -lc -lgcc -Wl,--end-group  "-L/tmp/arduino_build_6867"
/tmp/arduino_build_6867/libraries/VitoWifi/OptolinkP300.cpp.o: In function `OptolinkP300::_printHex(Print*, unsigned char*, unsigned char)':
/home/john/Arduino/scetchbooks/libraries/VitoWifi/OptolinkP300.cpp:407: undefined reference to `Logger::Logger()'
/tmp/arduino_build_6867/libraries/VitoWifi/OptolinkP300.cpp.o: In function `OptolinkP300::OptolinkP300()':
/home/john/Arduino/scetchbooks/libraries/VitoWifi/OptolinkP300.cpp:42: undefined reference to `Logger::Logger()'
/tmp/arduino_build_6867/libraries/VitoWifi/VitoWifi.cpp.o: In function `swap<unsigned int>':
/home/john/Arduino/scetchbooks/libraries/VitoWifi/VitoWifi.cpp:266: undefined reference to `Logger::Logger()'
collect2: error: ld returned 1 exit status
Using library VitoWifi in folder: /home/john/Arduino/scetchbooks/libraries/VitoWifi (legacy)
exit status 1
Error compiling for board WeMos D1 R2 & mini.

Contradiction in data point list

There is a contradiction in the data point lists:

VitoWiFi/doc/vt200ho1abc_en.pdf says party modus is read/write on 0x2330.

VitoWiFi/doc/20C2_Vitodens_200_300_333_Vitotronic_200_Typ_HO1.pdf says the address should be 0x2303.

What is correct?

Opinions for mergin protocols

A question for the users of the VitoWifi-library:
I'm going to merge the KW and 300 protocol into one library. Now I've got some options in my mind how I would do that:

  • make the VitoWifi class a template class using the protocol as parameter
  • create an extra interface library in which you set the protocol and choose between subclasses
  • use #define to set the right protocol
  • other possibilities?

I want minimal runtime impact and minimal binary size increase. (first is more important)
I want to avoid the latter as it will be overwritten everytime you pull updates from GH.

Serialmonitor "chksum 0x2d"

Installation specifics

  • Heating type: Vitoladens 300c with Vitotronic 200 KW6B
  • Protocol: KW
  • Board: ESP8266 (Wemos D1 mini.)
  • Hardware: SFH485P and SFH309FA

Symptom

i can't see any IR blinking signal with my smartphone camera.

i got this message after boot up.

load 0x4010f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0x2d
v951aeffa
~ld

��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
it looks like my esp8266 didn't boot up correctly or is this message normal?

need loop() delay of 100ms

I programmed a webserver which returns the data point. Work in progress, but seems to work.
So if you call http://192.168.1.18/read?DP=f8&ReadLen=2 in your browser, it will return the heater ID.
Seems to work, however, if I loop() too fast I get a nack error.

Here is the cut down version of my website handler.

getValues = true;
while (myOptolink.isBusy());  // wait for optolink to become available
myOptolink.readFromDP( address, readLen);  // issue read command
 
    
 while (getValues){
  delay(100);  // need 100ms delay or it will nack
  myOptolink.loop();

  if (myOptolink.available() > 0) {
     getValues=false;
  }
  if (myOptolink.available() < 0) {
     getValues=false;
  }
}

please find the delay command. It needs to be at least 100ms for the function to work properly. If it is smaller, it will get a nack error. Does loop() require any special attention when getting called ?

This is the full version of the website handler:

void readDP() { //Handler 
String message = "";
String argument=""; 
unsigned int address, readLen;

if (server.args() != 2) { server.send(200, "text/plain", "You must specify exaclty 2 arguments"); return;}
if (server.arg("DP") =="") { server.send(200, "text/plain", "DP argument not found"); return;}
if (server.arg("ReadLen") =="") { server.send(200, "text/plain", "ReadLen argument not found"); return;}
argument=server.arg("DP"); address = strtol(argument.c_str(),0,16); 
argument=server.arg("ReadLen"); readLen = argument.toInt();  
 
getValues = true;
while (myOptolink.isBusy());  // wait for optolink to become available
myOptolink.readFromDP( address, readLen);  // issue read command
 
    
 while (getValues){
  delay(100);  // need 100ms delay or it will nack
  myOptolink.loop();

  if (myOptolink.available() > 0) {
    uint8_t value[40] = {0};
    myOptolink.read(value);
    Serial1.print(F("Address "));
    Serial1.print( address, HEX);
    Serial1.print(F(" has value "));
    for (uint8_t i = 0; i < readLen; ++i) {
      Serial1.print(value[i], HEX);
    }
    Serial1.println();
    for (uint8_t i = 0; i <readLen; ++i) {
          if ( value[i] < 0x10) message +="0";
          message += String( value[i],HEX);
         }
    message += "\n";   
    
    getValues=false;
  }
  if (myOptolink.available() < 0) {
    Serial1.println(myOptolink.readError());
    getValues=false;
  }
}

Exception 28

void setup() {
  // setup VitoWifi using a global callback handler
  VitoWifi.addDatapoint("outsidetemp", "boiler", 0x5525,STAT);
  VitoWifi.addDatapoint("boilertemp", "boiler", 0xf802, STAT);
  VitoWifi.setGlobalCallback(globalCallbackHandler);
  VitoWifi.setup(&Serial);
  
  // setup VitoWifi using a global callback handler
  VitoWifi.enableLogger();
  VitoWifi.setLogger(&Serial1);


  Serial1.begin(115200);
  Serial1.println(F("Setup finished..."));
}

void loop() {
  static unsigned long lastMillis = 0;
  if (millis() - lastMillis > 60 * 1000UL) {  // read all values every 60 seconds
    lastMillis = millis();
    VitoWifi.readDatapoint("outsidetemp");
    VitoWifi.readDatapoint("boilertemp");
  }

  VitoWifi.loop();
}

crashes. Exception decoder shows:

Decoding 10 results
0x402033e4: VitoWifiInterface ::loop() at /home/john/Arduino/scetchbooks/libraries/VitoWifi/VitoWifi.cpp line 266
0x40203a41: HardwareSerial::available() at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp line 188
0x40204148: OptolinkP300::_clearInputBuffer() at /home/john/Arduino/scetchbooks/libraries/VitoWifi/OptolinkP300.cpp line 376
0x402040f0: Logger::write(unsigned char) at /home/john/Arduino/scetchbooks/libraries/VitoWifi/Logger.cpp line 41
0x40204240: Print::print(__FlashStringHelper const*) at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp line 101
0x402033d8: std::queue > >::front() at /home/john/Arduino/scetchbooks/libraries/VitoWifi/VitoWifi.cpp line 266
: (inlined by) VitoWifiInterface ::loop() at /home/john/Arduino/scetchbooks/libraries/VitoWifi/VitoWifi.cpp line 196
0x401068ee: millis at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_wiring.c line 183
0x4020268e: loop at /home/john/Arduino/github/VitoWifi/examples/readDatapoint/readDatapoint.ino line 47
0x40203f1c: loop_wrapper at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_main.cpp line 58
0x40100739: cont_wrapper at /home/john/ArduinoPortable/arduino-1.8.5_ESPgit/hardware/esp8266com/esp8266/cores/esp8266/cont.S line 81

ESP32 Communication issue

Hi,

I'm having problems to establish communication with the heater controller. When I attach the optolink nothing happens, serial monitor shows setup finished but then no data communication happens. I tried rebooting my heater system (required or not?) with ESP32 attached but that makes no difference. I'm not that familiar with serial communications so I'm having a hard time to debug this problem, could anyone assist based on my setup & info below? Is there a way to gain more insight in what could be failing? Any help/feedback would be much appreciated, thanks a lot!

Installation specifics

IMG_3546

  • code (based on basic-esp32.ino) but with serial 2 pins:
/*

This example defines three datapoints.
The first two are DPTemp type datapoints and have their own callback.
When no specific callback is attached to a datapoint, it uses the global callback.

Note the difference in return value between the callbacks:
for tempCallback uses value.getFloat() as DPTemp datapoints return a float.
globalCallback uses value.getString(char*,size_t). This method is independent of the returned type.

*/
#include <Arduino.h>
#include <VitoWiFi.h>

VitoWiFi_setProtocol(P300); //P300

DPTemp outsideTemp("outsideTemp", "boiler", 0x5525);
DPTemp boilerTemp("boilertemp", "boiler", 0x0810);
//DPStat pumpStat("pump", "heating1", 0x2906);

void tempCallbackHandler(const IDatapoint& dp, DPValue value) {
  float fahrenheit = 0;
  fahrenheit = (5.0 / 9) * (value.getFloat() + 32);
  Serial.print(dp.getGroup());
  Serial.print(" - ");
  Serial.print(dp.getName());
  Serial.print(": ");
  Serial.println(fahrenheit, 1);  // print with 1 decimal
}

void globalCallbackHandler(const IDatapoint& dp, DPValue value) {
  Serial.print(dp.getGroup());
  Serial.print(" - ");
  Serial.print(dp.getName());
  Serial.print(" is ");
  char value_str[15] = {0};
  value.getString(value_str, sizeof(value_str));
  Serial.println(value_str);
}

void setup() {
  outsideTemp.setCallback(tempCallbackHandler);
  boilerTemp.setCallback(tempCallbackHandler);
  VitoWiFi.setGlobalCallback(globalCallbackHandler);  // this callback will be used for all DPs without specific callback
                                                      // must be set after adding at least 1 datapoint
  VitoWiFi.setup(&Serial, 16, 17);  // RX then TX number
  Serial.begin(115200);
  Serial.println(F("Setup finished..."));
}

void loop() {
  static unsigned long lastMillis = 0;
  if (millis() - lastMillis > 60 * 1000UL) {  // read all values every 60 seconds
    lastMillis = millis();
    VitoWiFi.readAll();
  }
  VitoWiFi.loop();
}
  • Debugging:
    When running the code I get the explained behaviour, serial monitor only show feedback of setup then nothing… That is the only debug info I have.

17:05:55.270 -> mode:DIO, clock div:1
17:05:55.270 -> load:0x3fff0018,len:4
17:05:55.270 -> load:0x3fff001c,len:1044
17:05:55.270 -> load:0x40078000,len:10124
17:05:55.374 -> load:0x40080400,len:5856
17:05:55.374 -> entry 0x400806a8
17:05:55.374 -> Setup finished...

To check the opto link I tested the IR led with a simple blink sketch and that worked fine, same thing with the IR transistor.

Blocking after 6 hours

nstallation specifics
Heating type: Vitotronic 200 KW2
Protocol: KW
Board: ESP8266 Wemos D1 mini
Hardware: own IR components

Issue:
Sometimes the data transfer stopped and I had to reboot the VitoWifi ESP Board.
Then I made a watchdog in NodeRed, that after 3 Minutes of no MQTT data the link xxx.xxx.xxx.xxx/reboot is called by NodeRed to automatically restart the board. This works.

But there was a unexpected picture given: the reboot often happens each 6 hours. So is there any idea, why the VitoWifi is blocked after exactly 6 hours?

Thanks

Optolink remains busy after first write

using v1.00 P300 I use this routine for reading / writing:

bool readWriteDP (word address, byte Len, uint8_t* rawdata, bool Write = false ){
  unsigned long now = millis(); 
  while (myOptolink.isBusy() && ((millis()-now) < 3000)) 
        delay(10);  // wait for optolink to become available
  if (myOptolink.isBusy() ) { 
      Serial1.print(F("optolink busy "));
      return false;
  }

  if (!Write) 
      myOptolink.readFromDP( address, Len);  // issue read command
  else 
      return myOptolink.writeToDP( address, Len, rawdata);

  while (((millis()-now) < 3000)){
        myOptolink.loop();
        if (myOptolink.available() > 0) {
          myOptolink.read(rawdata);
             return true; 
        }
        if (myOptolink.available() < 0) {
          Serial1.println(myOptolink.readError());
          return false; 
        }
  }
  return false;
}

This works for reading quite fine until the first write attempt. I then get the message "optolink busy" . The write succeeded but blocks the optolink from then on. Serial output is:

READ 410500012000042a
ack
RCV 41090101200004dc00b400bf
ack
Address 2000 has value DC00B400 (<--this is my read access)
Address 2000 data DC00 (<--this is my write access)
WRITE 41070002200002dc0007
ack
RCV 410501022000022a
ack

Vito P300 stalls

Installation specifics

  • ** Vitocal 300 with Vitotronic WO1B
  • Protocol: P300
  • Board: Wemos D1 mini
  • Hardware: self-made

Symptom

What happens? NACK
When does it happen? after read
What would you expect? cyclic reads
...

Using the KW protocol I get:


⸮��⸮���⸮⸮�⸮�⸮⸮⸮�⸮���⸮�⸮⸮�⸮�⸮⸮�������������⸮��⸮���⸮���⸮⸮�⸮�⸮⸮��⸮rl�d⸮⸮|�⸮l⸮|�⸮l⸮�b|⸮⸮�⸮�⸮{⸮c⸮c⸮⸮gg⸮dnn⸮⸮⸮�c�p⸮⸮l{d{dx⸮g⸮����⸮�d�Ĝcg⸮|�l⸮��⸮c⸮⸮oo⸮�l⸮⸮l`�⸮��oo�$`���gr⸮⸮⸮gc�⸮�l�{⸮⸮o#⸮�d⸮⸮⸮p�⸮⸮⸮�⸮d`�⸮⸮n⸮�Setup finished...
INIT done.
READ outsidetemp
READ 5525
ack
DP outsidetemp succes
boiler - outsidetemp: -0.1
READ outsidetemp
READ 5525
ack
DP outsidetemp succes
boiler - outsidetemp: -0.1
READ outsidetemp
READ 5525
ack
DP outsidetemp succes
boiler - outsidetemp: -0.1
READ outsidetemp

Seems to work apart from the fact that -0.1 is totally wrong, it should be about 5.98 degrees.
If I use protocol 300 I get:

setup finished...
READ outsidetemp
READ 4105000155250282
ack
nack, timeout
READ outsidetemp
READ outsidetemp
READ outsidetemp
...
(after 10 minutes or so...)
READ 4105000155250282
ack
nack, timeout
READ outsidetemp
READ outsidetemp
READ outsidetemp

It reads fine once. There is no activity on the TX pin on consecutive read attempts.
And it is not displaying its interpretation of the received data.

I modified your readDatapoint sketch. I commented out the boilertemp datapoint and addded

 // setup VitoWifi using a global callback handler
  VitoWifi.enableLogger();
  VitoWifi.setLogger(&Serial1);

Temperature-Datapoint with 3 Bytes

Hey @bertmelis
my heat pump has some data points with 3 bytes. For example temperatures.
Address 0101 is the outside temperature on 2 bytes.
Address 01C1 is the outside temperature on 3 bytes.
the first two bytes are the value (little endian) and the 3rd is a status.
How can I read this data

Here is the data from the raw data:

20:55:44.021 -> READ 410500010101020a
20:55:44.021 -> ack
20:55:44.058 -> RCV 410701010101023d004a
20:55:44.058 -> ack
20:55:44.058 -> Address 101 has value 3D000F8
20:55:44.058 -> READ 4105000101c103cb
20:55:44.091 -> ack
20:55:44.091 -> RCV 4108010101c1033d00404c
20:55:44.091 -> ack
20:55:44.091 -> Address 1C1 has value 3D0400F8

Unfortunately, the HEX is sometimes put together incorrectly. According to the raw data, this should be 3D0040F8.
So converted 003D-->61-->6.1°C
40-->Status (can be omitted)

But how can I create that as a data point?

Callback with old value after write datapoint

I create a bridge between vitowifi and openhab via mqtt.
Therefore I implemented a method which publishes all read values via mqtt as global callback.
Therefore I call readAll values in the esp loop. Then the global callback of vitowifi publishes all values via mqtt. That works quite well.
For writing thr sketch listens to mqtt and call writeDataPoint accordingly.
The problem is, that immediately after the write the global callback is called with the old value and this outdated value gets published via mqtt.

Is there a reason why vitowifi calls the callback with the old value after a write? I think the callback should not be invoked at all for writes.

What do you think?

4byte values KW protocol

Heating type: 2098 - Vitotronic 200 KW2
Protocol: KW
Board: ESP8266 NodeMCU
#################################
Hello Bert,
First of all I want to thank you for your work on this library, really cool stuff!

I have a problem reading 4byte values with the KW protocol. As soon as the first datapoint with 4 bytes is read, it returns ERROR -1, and all following readings fail, too.
My first thought about this is, could it be that " uint8_t _rcvBuffer[2]; " in "OptolinkKW.h" should be [4]?
I check that asap.

Siggi

No Data with ESP8266, but data with ESP32

Installation specifics

  • Heating type: Vitocal 200-s with WO1C
  • Protocol: KW or P300 both work
  • Board: ESP8266 NodeMCU and ESP32 NodeMCU

Symptom

Hey. With the Example Basic-ESP32 and an ESP32-Board I get Data on the Serial-Monitor by ArduinoIDE.
Connecting it to the ESP8266 NodeMCU on the GPIO1+3 there are no Data on the Serial-Monitor. Only two ? came on the Monitor. Can someone help me?

Cannot write (rawOptolink)

Installation specifics

  • Heating type: Vitodens 200
  • Protocol: P300
  • Board: Arduino Pro Mini ATmega328 5v 16MHz

Hi,
I am trying to write using the OptolinkP300 library and I am unable to do so. If I only try to read everything works ok. But when I try to write It seems to get stuck in busy state (the lcd prints quickly changing numbers + "busy" as it tries to do something and doesn't pass the !myOptolink.isBusy() condition.)

I'm working on another code and it does read ok until it tries to write, then it gets stuck in the busy state.

I couldn't find any example of how to write using the Optolink library.

BTW I had to modify few lines in the library to make it work with Arduino Pro Mini (I am using VisualStudio with Arduino plugin - maybe it's specific just to VisualStudio):

  • In OptolinkP300.hpp
class OptolinkP300 {
 public:
  OptolinkP300();
//#ifdef ARDUINO_ARCH_ESP32
//  void begin(HardwareSerial* serial, int8_t rxPin, int8_t txPin);
//#endif
//#ifdef ESP8266
  void begin(HardwareSerial* serial);
//#endif
  void loop();
  • In OptolinkP300.cpp
// begin serial @ 4800 baud, 8 bits, even parity, 2 stop bits
//#ifdef ARDUINO_ARCH_ESP32
//void OptolinkP300::begin(HardwareSerial* serial, int8_t rxPin, int8_t txPin) {
//  serial->begin(4800, SERIAL_8E2, rxPin, txPin);
//  _stream = serial;
//  // serial->flush();
//}
//#endif
//#ifdef ESP8266
void OptolinkP300::begin(HardwareSerial* serial) {
  serial->begin(4800, SERIAL_8E2);
  _stream = serial;
  // serial->flush();
}
//#endif

Example:
(Tries to write 27 °C to the set temperature register and then reads it).

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <OptolinkP300.hpp>
#include <Constants.hpp>

OptolinkP300 myOptolink;
#define lcd_width 16
LiquidCrystal_I2C lcd(0x27, lcd_width, 2);
#define room_temperature_day_address 0x2306 //(3..37) °C
#define room_temperature_day_length 1

#define pin_LED_alarm 5
#define pin_LED_communication 7
#define pin_LED_DEBUG 8
#define pin_LED_write LED_BUILTIN

uint32_t lastMillis = 0;
bool getValues = false;
boolean writeValues = false;
boolean readRequested = false;

void setup() {
    pinMode(pin_LED_alarm, OUTPUT);
    pinMode(pin_LED_communication, OUTPUT);
    pinMode(pin_LED_DEBUG, OUTPUT);
    pinMode(pin_LED_write, OUTPUT);

    myOptolink.begin(&Serial);
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("boot");

    //blink all LEDs top indicate the boot
    digitalWrite(pin_LED_alarm, HIGH);
    digitalWrite(pin_LED_communication, HIGH);
    digitalWrite(pin_LED_DEBUG, HIGH);
    digitalWrite(pin_LED_write, HIGH);
    delay(500);
    digitalWrite(pin_LED_alarm, LOW);
    digitalWrite(pin_LED_communication, LOW);
    digitalWrite(pin_LED_DEBUG, LOW);
    digitalWrite(pin_LED_write, LOW);

}

// the loop function runs over and over again until power down or reset
/*
//The loop has two states - getValues and writeValues
void loop() {
    myOptolink.loop();

    if (millis() - lastMillis > 10 * 1000UL) {
        lastMillis = millis();
        //RESET the LEDs
        digitalWrite(pin_LED_alarm, LOW);
        digitalWrite(pin_LED_communication, LOW);
        digitalWrite(pin_LED_DEBUG, LOW);
        lcd.clear();

        if (writeValues) { //sets state to get
            getValues = true;
            readRequested = false;
            writeValues = false;
            lcd.setCursor(0, 1);
            lcd.print("get");
        }
        else { //sets state to write
            getValues = false;
            writeValues = true;
            lcd.setCursor(0, 1);
            lcd.print("write");
        }

        digitalWrite(pin_LED_write, writeValues); //write LED is on when writing
    }

    if (getValues) {
        if (!myOptolink.isBusy()) {
            if (!readRequested) {
                digitalWrite(pin_LED_communication, HIGH);
                myOptolink.readFromDP(room_temperature_day_address, room_temperature_day_length);
                readRequested = true;
            }
        }
        else {
            lcd.setCursor(0, 0);
            lcd.print(millis());
            lcd.print("Busy");
        }
        if (readRequested) {
            if (myOptolink.available() > 0) {
                uint8_t value[4] = { 0 };
                myOptolink.read(value);

                if (value[0] == 27) {
                    digitalWrite(pin_LED_DEBUG, HIGH); //read data matches the written data
                }
                getValues = false;
                digitalWrite(pin_LED_communication, LOW);

            }
        }
    }

    if (writeValues) {
        if (!myOptolink.isBusy()) {
            digitalWrite(pin_LED_communication, HIGH);
            byte value[4] = { 27,0,0,0 };
            boolean err = !myOptolink.writeToDP(room_temperature_day_address, room_temperature_day_length, value);
            if (err) {
                digitalWrite(pin_LED_alarm, HIGH);
                lcd.setCursor(0, 0);
                lcd.print(millis());
                lcd.print("Write error");
            }
            digitalWrite(pin_LED_communication, LOW);
        }
        else {
            lcd.setCursor(0, 0);
            lcd.print(millis());
            lcd.print("Busy");
        }
    }

    if (myOptolink.available() < 0) { //error
        digitalWrite(pin_LED_alarm, HIGH);
        lcd.setCursor(0, 0);
        lcd.print(millis());
        lcd.print("error");
        lcd.print(myOptolink.readError());
    }
}

Edit: I tried to compile the same code with Arduino IDE and it does exactly the same thing.

Feature request: sniffer example

as the information on the available data points is ... hm heterogeneous to say at least, how about a scanner ?

An example file to probe all data points from 0x0000 to 0xffff and return the number of payload bytes and possible interpretations as table. Skip nack errors E.g

Address bytes uint int double
0x1000 4 13 13 1.234

The size of uint and int numbers can be taken from the size of the payload.

Besides, it would probably reveal all uncertainties in error handling :-)

protocol blocked after error

Hello
I have experienced your vitoWifi library on ESP8266nodeMCU and a Vitobens 222W and the protocol P300 works well
Nevertheless if a mistake happens on the connection the system doesn't recover.

if it is a bad identifier or bad length problem, vitoWifi produces after only reading with "optolink.available <0" even on good adresses and lengths requests.

if it is a transmission problem like the optical path obscured, the system doesn't respond anymore (probably due to an UART crash)
Can you help to fix these 2 problems

Best regards

...

Be as complete as you can!

Extra info

Please add relevant debug information like debug messages, (decoded) stack traces...

You don't have to provide all the info, but less is not always more!

Optolink connection failed

Installation specifics

  • Heating type: Vitodens 300-W Typ WB3C with a Vitotronic 200
  • Protocol: P300
  • Board: ESP32 mit Adafruit Huzzah32 Feather auf dem Proto Feather Wing
  • Hardware: Which hardware implementation did you use?

Symptom

Optolink connection failed
Could you please recommend a testing strategy for me ?
What is the best way to check why the communication via the Optolink is not possible ?
Is there anything to do on the Vitotronic to allow the communication via the Optolink ?

@bertmelis

First of all i would like to say thank you for your excellent work and for your willingness to share this work.

I have a Vitodens 300-W Typ WB3C with a Vitotronic 200 installed and i try to build a Optolink interface based on the building instruction
ESP32 mit Adafruit Huzzah32 Feather auf dem Proto Feather Wing and your software VitoWifi

The goal is to use your esp-boiler software with VitoWifi, EspMqtt and WIfiPrinter to integrate the boiler information into openHAB.

Currently i am able to bring the Huzzah32 into the Wlan and connect him with the MQTT broker but i am not able to establish a connection between the Huzzah32 and the Vitotronic via the Optolink.

Currently i use only your rawOptolink module to reduce the complexity to establish a connection via the Optolink.

I added some debugging information into the code so i can see that the function _initHandler is performed in a loop and that no stream seems to be available.

On the Proto Wing board i use a SFH309FA and TSHA4401 for the Optolink. I checked the TSHA4401 with a smartphone camera and can see that she is blinking.

Could you please recommend a testing strategy for me ?
What is the best way to check why the communication via the Optolink is not possible ?
Is there anything to do on the Vitotronic to allow the communication via the Optolink ?

r/*

This example defines 3 datapoints of type "TEMP" in a struct array.
Every minute, the array is iterated.

For each Datapoint, the read value is printed as HEX in Serial1

*/

#include <OptolinkP300.h>

HardwareSerial Serial1(1);
// Choose two free pins
#define SERIAL1_RXPIN 16
#define SERIAL1_TXPIN 17

OptolinkP300 myOptolink;
uint32_t lastMillis = 0;
bool getValues = false;
uint8_t currentIndex = 0;

// Define struct to hold Viessmann datapoints
struct Datapoint {
  uint16_t address;
  uint8_t length;
};
const Datapoint Datapoints[] = {
    0x5525, 2,  // outside temp
    0x0810, 2,  // boiler temp
    0x0812, 2   // DHW temp
};
uint8_t numberOfDatapoints = sizeof(Datapoints) / sizeof(*Datapoints);



//******************************************************************************
// Setup
//******************************************************************************
//
void setup() {
  delay(10000);					// time to reattach serial debug tool
  Serial.println(F("setup - started"));

  Serial.begin(115200);

  // Start Viessmann communication on Serial1
  myOptolink.begin(&Serial1, SERIAL1_RXPIN, SERIAL1_TXPIN);
  Serial.println(F("setup - myOptolink.begin"));

  myOptolink.setLogger(&Serial);
  Serial.println(F("setup - myOptolink.setLogger"));

  Serial.println(F("setup - ended"));
}



//******************************************************************************
// Loop
//******************************************************************************
//
void loop() {
  Serial.println(F("loop - started"));

  // put loop() function inside main loop
  myOptolink.loop();

  if (millis() - lastMillis > 1 * 60 * 1000UL) {  // get values every 1 minute
    lastMillis = millis();
    getValues = true;
    currentIndex = 0;
  }

  if (getValues) {
	  Serial.println(F("loop - getValues"));
    if (!myOptolink.isBusy()) {
      myOptolink.readFromDP(Datapoints[currentIndex].address, Datapoints[currentIndex].length);
    }
  }

  if (myOptolink.available() > 0) {
	  Serial.println(F("loop - available > 0"));
    uint8_t value[4] = {0};
    myOptolink.read(value);
    Serial.print(F("Address "));
    Serial.print(Datapoints[currentIndex].address, HEX);
    Serial.print(F(" has value "));
    for (uint8_t i = 0; i <= 4; ++i) {
      Serial.print(value[i], HEX);
    }
    Serial.println();
    ++currentIndex;
  }

  if (myOptolink.available() < 0) {
	  Serial.println(F("loop - available < 0"));
    Serial.println(myOptolink.readError());
    ++currentIndex;
  }

  if (currentIndex >= numberOfDatapoints) getValues = false;

  Serial.println(F("loop - ended"));
}

Any help would be appreciated.

Best regards

Jürgen

Implement GWG protocol

Hello I have a vitodens 100 wb1.
I have the "Bauanleitung-ESP8266" + esp-link and vitocontold (I also tried with python script which are also working for low level read).
I just began research for the adresses.
I had some results with this : openv/openv#442
I am very interrested about your work.
Would be nice to use vitowifi for GWG protocol also

PS : I have already forked your project here : https://github.com/Arty68/VitoWiFi/tree/master/src and tried to add GWG Support but I could use some help to check if everything is ok :)

P300 does not recover from "nack, comm error"

if that error was triggered once, e.g. by an read attempt to a wrong address, it does not recover from it. All consecutive read requests quit with error 3 without even attempting to send something.

V1: protocol blocked after invalid DP address

Installation specifics

ESP8266 + Vitotronic200 + Vitocal300

Symptom

What happens? (crash, unresponsive, nothing at all...)
I cannot communicate with the heater when I use a wrong DP address. It does not recover.
As I am currently scanning the heater for all responsive data points, this cannot be avoided by nature.

When does it happen? (after several hours, immideately...)
immediately

What would you expect?
It should recover when I use a correct address, instead I need to reboot.

I have a workaround. In Optolink300.cpp, change line 285 in function void OptolinkP300::_receiveHandler() from

_setState(RESET);

to

_setState(IDLE);

I have to admit I did not dig too deep into the protocol stack and I cannot explain whats wrong with reset, but it did solve my issue.
Bert, do you know why RESET is inappropriate at this point ? Technically a wrong DP address is not an error.

Datatypes request

a) device type

2 bytes. Currently using COUNTS as the only 2-byte datatype available:



READ 4105000100f80200
ack
RCV 4107010100f80220496c
ack
DP Gerätekennung succes
boiler-Gerätekennung:18720

result is 18720 / 0x4920
should be: 0x2049, at least it is referred to as 0x2049 in the table in https://openv.wikispaces.com/Adressen. Not sure who swapped the bytes ;-) If they did- ignore this request.

b) operating time

currently using COUNT, returning seconds. Hmm... not much use. Would prefer hours as used by the display of the Vitotronic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.