Menu

EIS10 patch to enable counter object

Ben08
2008-07-06
2012-12-14
  • Ben08

    Ben08 - 2008-07-06

    In order to use a EIS10 counter object in linknx (monitors my elctricity use) I amended the objectcontroller sources.  My C++ skills are fairly limited, you will spot the striking similarity to other parts in the code.

    To declare a variable as a counter object, you need to specify the type as "EIS10" in your config.xml.  All other operations are the usual ones (gt,gte,....) and should work normally.

    The two patches in the following posts need to be applied agains the current CVS sources (I assume that this will be release 0.0.1.24), but you will surely be able to apply them to previous versions of linknx with minor modifications (object type (config.xml) seems to be differently handled in the latest CVS version compared to release <= 0.0.1.23).

    A big thank you goes to Jean-François for his software which is in equal measures help- and powerful.

    Regards,
    Bernhard
      

     
    • Ben08

      Ben08 - 2008-07-06

      --- objectcontroller.horg    2008-03-09 23:42:59.000000000 +0000
      +++ objectcontroller.h    2008-07-05 14:18:38.000000000 +0100
      @@ -235,6 +235,35 @@
           double value_m;
      };

      +// EIS 10 counter object extension ------------------------
      +
      +class CounterObject : public Object
      +{
      +public:
      +    CounterObject();
      +    virtual ~CounterObject();
      +
      +    virtual ObjectValue* createObjectValue(const std::string& value);
      +    virtual bool equals(ObjectValue* value);
      +    virtual int compare(ObjectValue* value);
      +    virtual void setValue(ObjectValue* value);
      +    virtual void setValue(const std::string& value);
      +    virtual std::string getValue();
      +    virtual std::string getType() { return "EIS10"; };
      +
      +    virtual void doWrite(const uint8_t* buf, int len, eibaddr_t src);
      +    virtual void doSend(bool isWrite);
      +    void setIntValue(int value);
      +    int getIntValue()
      +    {
      +        if (!init_m)
      +            read();
      +        return value_m;
      +    };
      +protected:
      +    int value_m;
      +};
      + // EIS 10 counter object extension -------------------------
      class ScalingObject : public Object
      {
      public:
      @@ -361,6 +390,19 @@
           double value_m;
      };

      +class CounterObjectValue : public ObjectValue
      +{
      +public:
      +    CounterObjectValue(const std::string& value);
      +    virtual ~CounterObjectValue() {};
      +    virtual std::string toString();
      +protected:
      +    CounterObjectValue(int value) : value_m(value) {};
      +    CounterObjectValue() {};
      +    friend class CounterObject;
      +    int value_m;
      +};
      +
      class ScalingObjectValue : public ObjectValue
      {
      public:

       
    • Ben08

      Ben08 - 2008-07-06

      --- objectcontroller.cpporg    2008-03-09 23:42:59.000000000 +0000
      +++ objectcontroller.cpp    2008-07-05 22:05:22.000000000 +0100
      @@ -49,6 +49,10 @@
               return new ValueObject();
           else if (type == "EIS6")
               return new ScalingObject();
      +// EIS 10 counter extension --------------
      +    else if (type == "EIS10")
      +        return new CounterObject();
      +// EIS 10 counter extension --------------
           else if (type == "heat-mode")
               return new HeatingModeObject();
           else if (type == "EIS15")
      @@ -500,6 +504,32 @@
           out << value_m;
           return out.str();
      }
      +// Counter extension EIS10 -------------------
      +CounterObjectValue::CounterObjectValue(const std::string& value)
      +{
      +    std::istringstream val(value);
      +    val >> value_m;
      +
      +    if ( val.fail() ||
      +         val.peek() != std::char_traits<char>::eof() || // workaround for wrong val.eof() flag in uClibc++
      +         value_m > 65535 ||
      +         value_m < 0)
      +    {
      +        std::stringstream msg;
      +        msg << "CounterObjectValue: Bad value: '" << value << "'" << std::endl;
      +        throw ticpp::Exception(msg.str());
      +    }
      +}
      +
      +std::string CounterObjectValue::toString()
      +{
      +    std::ostringstream out;
      +    out << value_m;
      +    return out.str();
      +}
      +
      +
      +// Counter extension EIS10 end -------------------

      ScalingObjectValue::ScalingObjectValue(const std::string& value)
      {
      @@ -1200,7 +1230,7 @@
      {
           if (len < 4)
           {
      -        std::cout << "Invlalid packet received for ValueObject (too short)" << std::endl;
      +        std::cout << "Invalid packet received for ValueObject (too short)" << std::endl;
               return;
           }
           double newValue;
      @@ -1260,6 +1290,113 @@
               onUpdate();
           }
      }
      +// Counter extension EIS10 --------------------------------
      +
      +CounterObject::CounterObject() : value_m(0)
      +{}
      +
      +CounterObject::~CounterObject()
      +{}
      +
      +ObjectValue* CounterObject::createObjectValue(const std::string& value)
      +{
      +    return new CounterObjectValue(value);
      +}
      +
      +bool CounterObject::equals(ObjectValue* value)
      +{
      +    assert(value);
      +    CounterObjectValue* val = dynamic_cast<CounterObjectValue*>(value);
      +    if (val == 0)
      +    {
      +        std::cout << "CounterObject: ERROR, equals() received invalid class object (typeid=" << typeid(*value).name() << ")" << std::endl;
      +        return false;
      +    }
      +    if (!init_m)
      +        read();
      +    std::cout << "CounterObject (id=" << getID() << "): Compare value_m='" << value_m << "' to value='" << val->value_m << "'" << std::endl;
      +    return value_m == val->value_m;
      +}
      +
      +int CounterObject::compare(ObjectValue* value)
      +{
      +    assert(value);
      +    CounterObjectValue* val = dynamic_cast<CounterObjectValue*>(value);
      +    if (val == 0)
      +    {
      +        std::cout << "CounterObject: ERROR, compare() received invalid class object (typeid=" << typeid(*value).name() << ")" << std::endl;
      +        return false;
      +    }
      +    if (!init_m)
      +        read();
      +    std::cout << "CounterObject (id=" << getID() << "): Compare value_m='" << value_m << "' to value='" << val->value_m << "'" << std::endl;
      +
      +    if (value_m == val->value_m)
      +        return 0;
      +    if (value_m > val->value_m)
      +        return 1;
      +    else
      +        return -1;
      +}
      +
      +void CounterObject::setValue(ObjectValue* value)
      +{
      +    assert(value);
      +    CounterObjectValue* val = dynamic_cast<CounterObjectValue*>(value);
      +    if (val == 0)
      +        std::cout << "CounterObject: ERROR, setValue() received invalid class object (typeid=" << typeid(*value).name() << ")" << std::endl;
      +    setIntValue(val->value_m);
      +}
      +
      +void CounterObject::setValue(const std::string& value)
      +{
      +    CounterObjectValue val(value);
      +    setIntValue(val.value_m);
      +}
      +
      +std::string CounterObject::getValue()
      +{
      +    return CounterObjectValue(getIntValue()).toString();
      +}
      +
      +void CounterObject::doWrite(const uint8_t* buf, int len, eibaddr_t src)
      +{
      +    int newValue;
      +    int d1 = ((unsigned char) buf[2]) * 256;
      +    int d2 = ((unsigned char) buf[3]);
      +    newValue = d1 + d2;
      +    if (!init_m || newValue != value_m)
      +    {
      +        std::cout << "New value " << newValue << " for Counter object " << getID() << std::endl;
      +        value_m = newValue;
      +        init_m = true;
      +        onUpdate();
      +    }
      +}
      +
      +void CounterObject::doSend(bool isWrite)
      +{
      +    uint8_t buf[4] = { 0, (isWrite ? 0x80 : 0x40), 0,0};
      +
      +    buf[2] = ((value_m >> 8) & 0xff);
      +    buf[3] = (value_m & 0xff);
      +
      +    Services::instance()->getKnxConnection()->write(getGad(), buf, 4);
      +}
      +
      +void CounterObject::setIntValue(int value)
      +{
      +    if (!init_m || value != value_m || (flags_m & Force))
      +    {
      +        value_m = value;
      +        if ((flags_m & Transmit) && (flags_m & Comm))
      +            doSend(true);
      +        init_m = true;
      +        onUpdate();
      +    }
      +}
      +
      +// Counter extension EIS10 end --------------------------------

      ScalingObject::ScalingObject() : value_m(0)
      {}

       
    • jef2000

      jef2000 - 2008-07-29

      Hi,

      I have added support for a couple of new data-types. 32 bit IEEE floats, 8, 16 and 32 bits signed and unsigned integers. Now I use the numeric datatypes as described in
      http://www.knx.org/fileadmin/downloads/03%20-%20KNX%20Standard/KNX%20Standard%20Public%20Documents/03_07_02%20Datapoint%20Types%20v13%20AS.zip

      For example "EIS1" is replaced by "1.001" , "EIS5" by "9.xxx", "EIS10" by "7.xxx".
      For "EIS6", the replacement is "5.xxx" but if you use "5.001", the value displayed will be between 0 and 100 instead of 0 and 255. If you use "5.003", the displayed value will be between 0 and 360.

      I hope I'll be able to make an official release in the coming weeks, but I still have a couple of things to fix before.

      Regards,

      Jean-François

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.