Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ISKRAemeco MT174 and Siemens TD3511 #46

Closed
andig opened this issue Nov 1, 2014 · 0 comments
Closed

Fix ISKRAemeco MT174 and Siemens TD3511 #46

andig opened this issue Nov 1, 2014 · 0 comments

Comments

@andig
Copy link
Contributor

andig commented Nov 1, 2014

https://www.mail-archive.com/search?l=volkszaehler-dev%40lists.volkszaehler.org&q=from%3A%22Sebastian+Michel%22&o=newest&f=1

Hallo zusammen,

also es funktioniert nun sowohl mit dem ISKRAemeco MT174 als auch dem
Siemens TD3511. Anbei findet ihr den Patch. Ich hab versucht sowenig
Änderungen zu machen wie es geht. Hier nochmal die Zusammenfassungen:

  1. Das Device wird im blocking mode geöffnet. Das führte bei mir dazu,
    dass die read() Funktion mit 0 zurückkehrt. Das heißt normalerweise ein
    eof oder derartiges. Sowas sollte bei einem seriellen Device niemals
    passieren. Ich weiß auch nicht warum das der Fall ist.
  • Ich hab den Code dahingehend geändert, dass das Device im
    non-blocking mode geöffnet wird. Damit funktioniert's nun.
  1. Die Statemachine sollte niemals unendlich warten und irgendwo hängen
    bleiben.
  • Ich hab ein Timeout von 10s eingebaut. Also wenn innerhalb 10s keine
    Daten empfangen werden bzw. beim Start kein Sync-byte kommt, wird dieser
    Lesevorgang abgebrochen.
  1. Die Statemaching wird immer beim Empfang eines '/' zurückgesetzt. Da
    mein Zähler ein '/' im Identification String sendet, hängt sich die
    Statemachine auf.
  • Das habe ich rausgenommen.
  1. Mein Zähler sendet ca. 330 obis-codes. Da ist dann sowas dabei wie
    2.8.1_16, 2.8.1_15 usw. Ich interessiere mich eigentlich nur für die
    Einträge von 2.8.0. Das ist insofern ein Problem, dass der D0-Meter nur
    maximal 32 Einträge zulässt. Das heißt bis die interessanten codes
    ankommen, sind die 32 Einträge schon längst belegt.
  • Ich filtere jetzt nur noch obis-codes heraus die ein value und eine
    Einheit besitzen. Damit kommen bei meinem Zähler genau 32 zusammen.
  1. Der Zähler sendet ungültige Obis-Codes. Zumindest ist der string für
    die Klasse Obis.cpp nicht auswertbar. Das führt dazu, dass vzlogger
    abstürzt. Vermutlich sind es die obis-codes die unter anderem Buchstaben
    statt Zahlen haben.
  • Ich hab die Stellen mit einem try-except Block abgefangen und
    überspringe die betroffenen obis-codes.
  1. Fehler beim Setzen der Parity
  • Das hab ich korrigiert.

Weiterhin habe ich mal die Ausgaben der beiden Zähler angehangen, mit
denen das getestet wurde.

Gruß
Sebastian

ISKRAemeco_MT174.txt
Description: Binary data


Siemens_TD-3511.txt
Description: Binary data
diff --git a/src/Obis.cpp b/src/Obis.cpp
index f918797..eebf5f8 100644
--- a/src/Obis.cpp
+++ b/src/Obis.cpp
@@ -192,7 +192,7 @@ int Obis::parse(const char *str) {
 }

 int Obis::lookup_alias(const char *alias) {
-   for (const obis_alias_t *it = aliases; it != NULL; it++) {
+   for (const obis_alias_t *it = aliases; !it-id.isNull(); it++) {
        if (strcmp(it-name, alias) == 0) {
            *this = it-id;
            return SUCCESS;
diff --git a/src/protocols/MeterD0.cpp b/src/protocols/MeterD0.cpp
index f48f864..cc74146 100644
--- a/src/protocols/MeterD0.cpp
+++ b/src/protocols/MeterD0.cpp
@@ -204,6 +204,13 @@ ssize_t MeterD0::read(std::vectorReadingrds, size_t max_readings) {
    char byte;          /* we parse our input byte wise */
    int byte_iterator; 
    size_t number_of_tuples;
+int bytes_read;
+
+time_t start_time;
+time_t end_time;
+
+// get current time
+time(start_time);

    if(_pull.size()) {
        int wlen=write(_fd,_pull.c_str(),_pull.size());
@@ -215,12 +222,41 @@ ssize_t MeterD0::read(std::vectorReadingrds, size_t max_readings) {

    context = START;/* start with context START */

-   while (::read(_fd, byte, 1)) {
-       if (byte == '/') context = START;   /* reset to START if / reoccurs */
-       else if (byte == '!') context = END;    /* ! is the identifier for the END */
+   while (1) {
+
+// check if timed out
+time(end_time);
+if (difftime(end_time, start_time)  10)
+{
+ print(log_error, nothing received for more than 10 seconds, name().c_str());
+ break;
+}
+
+// now read a single byte
+bytes_read = ::read(_fd, byte, 1);
+if (bytes_read == 0 || bytes_read == -1  errno == EAGAIN)
+{
+// wait and read again
+usleep(5000);  // 5 ms
+continue;
+}
+else if (bytes_read == -1)
+{
+// an error occured reading a byte
+print(log_error, error reading a byte (%d), name().c_str(), errno);
+break;
+}
+
+// reset timeout
+if (context != START)
+{
+time(start_time);
+}
+
+       if (byte == '!') context = END; /* ! is the identifier for the END */
        switch (context) {
 case START:            /* strip the initial / */
-if  (byte != '\r'   byte != '\n') { /*allow extra new line at the start */
+if  (byte == '/') {
   byte_iterator = number_of_tuples = 0;/* start */
   context = VENDOR;/* set new context: START - VENDOR */
 }
@@ 
This was referenced Nov 2, 2014
@andig andig closed this as completed Nov 3, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant