This page last changed on Mar 26, 2011 by josep.

A couple of days ago, I tried to create a model with a KNX slider, which apparently requires a sensor. The application was to be able to control (and get feedback) on a variable intensity light.

Well, after trying several "command" words for reading the status with no results, I finally decided to access the source code to figure out what the right command was for level-type sensors to use.

Well, if I read the source correctly, it seems to me that this cannot be done in the current code base. However, the way I am reading the code it seems a simple matter of defining a new verb (instead of STATUS) which actually sets up the proper APDU ... This would solve my immediate problem, although I am not sure it would be the right solution long term, as the mechanism being used to resolve the name is a simple dictionary lookup...

In any case, after this, I would have a couple of questions:
1. Is there a deep reason why there is only the "STATUS" entry for read commands? If not, is there a work item in place to fix this situation? If not, what is the procedure to get
such work item in place, even to resolve it? (sorry if this is discussed somewhere else in the site, have not had time to browse through everything)

2. Besides "fixing" the above missing feature, is there a way in which I can fruitfully implement a slider control for a variable light in a KNX system with the current code base?

Thanks,

Josep

Status reads for DPT 5.xxx should be in, and I seem to recall some users setting up their sliders so it should work (don't have any DPT 5.xxx gear to test with personally)

The command is still 'STATUS', your sensor needs to be RANGE or LEVEL type to indicate it returns integer values.

See here: https://openremote.svn.sourceforge.net/svnroot/openremote/trunk/Controller/src/org/openremote/controller/protocol/knx/GroupValueRead.java

Posted by juha at Mar 27, 2011 10:51

This part of the code is very confusing though:

  /*
   * IMPLEMENTATION NOTE:
   *
   *   if new valid values for command names are added, the unit tests should be added
   *   accordingly into KNXCommandBuilderTest
   */
  static
  {
    booleanCommandLookup.put("STATUS", ApplicationProtocolDataUnit.READ_SWITCH_STATE);
  }

As it implies it only reads switch DPT – where in fact the read request payload is the same regardless of the datatype.

Posted by juha at Mar 27, 2011 11:05

Juha,
thanks for answering.

I believe that was the intention, as you say, to provide one command (STATUS) for both data types. You mention other users have been able to set up sliders for KNX with the current code base unmodified. I would love to see those solutions, as I certainly am not able to do so, and looking at the code, it would greatly surprise me if others were able to achieve it.

Let me explain.

The above code snippet is not that confusing, it sets up the

   ApplicationProtocolDataUnit.READ_SWITCH_STATE 

as the APDU associated with the STATUS command. This has consequences in the Read method, where the following line:

    DataPointType dpt = getAPDU().getDataPointType();

makes dpt satisfy the following relationship:

   dpt == ApplicationProtocolDataUnit.READ_SWITCH_STATE.getDataPointType();

But from the definition of the above constant in ApplicationProtocolDataUnit.java

  /**
   * Represents the full APDU (APCI bits) for Group Value Read request for data points with
   * DPT 1.001 (Switch) type.
   *
   * @see ApplicationLayer.Service#GROUPVALUE_READ
   * @see org.openremote.controller.protocol.knx.datatype.Bool#READ_SWITCH
   */
  final static ApplicationProtocolDataUnit READ_SWITCH_STATE = new ApplicationProtocolDataUnit
  (
      ApplicationLayer.Service.GROUPVALUE_READ,
      Bool.READ_SWITCH
  );

will ensure that the following holds:

ApplicationProtocolDataUnit.READ_SWITCH_STATE.getDataPointType() == Bool.READ_SWITCH.getDataPointType();

which, after inspecting the relevant code in Bool.java:

  /**
   * Datatype used for Group Value Read service with 'SWITCH' device.
   *
   * @see org.openremote.controller.protocol.knx.datatype.DataPointType.BooleanDataPointType#SWITCH
   */
  public final static DataType READ_SWITCH = new DataType()
  {
    public int getDataLength()
    {
      return 1;
    }

    public byte[] getData()
    {
      return new byte[] { 0x00 };
    }

    public DataPointType getDataPointType()
    {
      return DataPointType.BooleanDataPointType.SWITCH;
    }
  };

tells us that the following relationship holds:

dtp == DataPointType.BooleanDataPointType.SWITCH

Now, going back to the Read method in the file you pointed me to above, we find the relevant branch of the if statement (for a LEVEL sensor):

    else if (sensorType == EnumSensorType.LEVEL)
    {
      if (dpt == DataPointType.Unsigned8BitValue.SCALING)
      {
        Unsigned8Bit valueDPT = (Unsigned8Bit)responseAPDU.getDataType();

        return Integer.toString(valueDPT.resolve());
      }

      else if (dpt == DataPointType.Unsigned8BitValue.ANGLE)
      {
        Unsigned8Bit valueDPT = (Unsigned8Bit)responseAPDU.getDataType();

        return Integer.toString((int)(valueDPT.resolve() / 3.6));
      }

      else if (dpt == DataPointType.Unsigned8BitValue.RELPOS_VALVE)
      {
        Unsigned8Bit valueDPT = (Unsigned8Bit)responseAPDU.getDataType();

        return Integer.toString((int)(valueDPT.resolve() / 2.55));
      }

      else if (dpt == DataPointType.Unsigned8BitValue.VALUE_1_UCOUNT)
      {
        Unsigned8Bit valueDPT = (Unsigned8Bit)responseAPDU.getDataType();

        return Integer.toString((int)(valueDPT.resolve() / 2.55));
      }

      else
      {
        throw new Error("Unrecognized datatype for LEVEL sensor: " + dpt);
      }
    }

Inspection of this code seems to indicate that dpt is not equal to any of the DataPoinType(s) it is checked against, which results in the code taking the default (else) branch, and throwing the exception that appears in there.
This, BTW, is consistent with the output I see in the console from which I launch the controller:

Exception in thread "Thread-12" java.lang.Error: Unrecognized datatype for LEVEL sensor: 1.001

Given the above, I can see two approaches:

1. Introduce a new command, different from STATUS, and associate it with the right APDU
2. Extend the above if statement to also contemplate the datatype 1.001 (DataPointType.BooleanDataPointType.SWITCH). Given what you say about the frame being the same, this approach would work

Does it make sense?

Thanks again,

Josep
(I edited my post)
With the proposed option 2, the code would read as follows:

    else if (sensorType == EnumSensorType.LEVEL)
    {
      if (dpt == DataPointType.Unsigned8BitValue.SCALING || dpt == DataPointType.BooleanDataPointType.SWITCH)
      {
        Unsigned8Bit valueDPT = (Unsigned8Bit)responseAPDU.getDataType();

        return Integer.toString(valueDPT.resolve());
      }

      else if (dpt == DataPointType.Unsigned8BitValue.ANGLE)
      {
        Unsigned8Bit valueDPT = (Unsigned8Bit)responseAPDU.getDataType();

        return Integer.toString((int)(valueDPT.resolve() / 3.6));
      }

      else if (dpt == DataPointType.Unsigned8BitValue.RELPOS_VALVE)
      {
        Unsigned8Bit valueDPT = (Unsigned8Bit)responseAPDU.getDataType();

        return Integer.toString((int)(valueDPT.resolve() / 2.55));
      }

      else if (dpt == DataPointType.Unsigned8BitValue.VALUE_1_UCOUNT)
      {
        Unsigned8Bit valueDPT = (Unsigned8Bit)responseAPDU.getDataType();

        return Integer.toString((int)(valueDPT.resolve() / 2.55));
      }

      else
      {
        throw new Error("Unrecognized datatype for LEVEL sensor: " + dpt);
      }
    }
Posted by josep at Mar 27, 2011 12:47

Thanks for the post and analyzing it – will need to look at it again. Do note that the sent APDU and the response APDU are not the same instances but it is possible the response APDU gets incorrectly initialized due to the datatype in the group read request being inappropriate in the first place.

The fix as you propose is not the correct one though – SCALING, ANGLE, RELPOS_VALVE and VALUE_1_UCOUNT are all same basic datatype (8-bit values) so would suffer from the same issue, and logically comparing to SWITCH on something that is an 8-bit integer wouldn't be correct (rather, the APDU would need to contain the right datatype in the first place).

However, before going futher, can you please post the XML snippet of your STATUS command from controller.xml just to ensure that it in fact defines the DPT correctly (5.xxx) rather than uses the 1.001 which the exception reports. It should contain a property

<property name = "dpt" value = "5.001"/>

somewhere in your controller.xml

Thanks again for digging deep into this.

Posted by juha at Mar 27, 2011 17:41

Just wanted to add:

In principal your first solution is correct – adding new keywords, been on my TODO for a very long time. Mainly it serves to make the DPT's in the commands implicit, ie. 'READ SWITCH' automatically means 1.001 where as 'READ SCALE' becomes 5.001 automatically. And therefore we can drop the requirement of feeding in DPT from the user altogether.

If you're able to send a patch to that effect, would be welcome (you uncovered most of the code already).

PS. the coupling of DPT to response APDU is in the KNXConnectionManager, through KNXCommand.getDataType() call. Didn't check yet whether that gets set through the controller.xml DPT property, or somehow gets linked to the group read command's DPT (which is the incorrect 1.001 one). One a quick glance it looks like it should be the DPT you specify in controller.xml file.


    public ApplicationProtocolDataUnit read(GroupValueRead command)
    {
      this.sendInternal(command);

      ApplicationProtocolDataUnit.ResponseAPDU response = busListener.internalState.get(command.getAddress());

      if (response == null)
      {
        return null;
      }

      DataPointType dpt = command.getDataPointType();

      return response.resolve(dpt);
    }

However, more unit tests are needed in this area.

Posted by juha at Mar 27, 2011 18:01

Juha,

the relevant XML is this:

    <command id="208" protocol="knx">
      <property name="command" value="status" />
      <property name="groupAddress" value="2/1/6" />
      <property name="DPT" value="5.001" />
    </command>

...

    <sensor id="190" name="Salon Mesa Nivel" type="level">
      <include type="command" ref="208" />
    </sensor>
Posted by josep at Mar 27, 2011 18:11

Thanks,

That looks correct. The original DPT from the config doesn't make it to the response APDU then.

Think the best way is to add the new mapping to replace 'STATUS'.

Posted by juha at Mar 27, 2011 18:14

Sure, I believe the change is relatively straightforward.
My only problem is that I am not familiar with the toolset you guys are using (sorry, never contributed to sourceforge projects), never used svn, and do not know which other toolsets you are using, or what yor standards for code review are.

So, if you point me to somewhere where I can be educated about the above questions, I will spend the time to submit the short-term patch.

Jose

Posted by josep at Mar 27, 2011 18:15

Building the controller, you can follow the instructions here: Building OpenRemote 2.0 Developer Releases

Once you have a version that works for you, you can either send the diff output ('svn diff' command) or if by that time you're more comfortable with svn, you can create a sourceforge account and apply the patch yourself.

Posted by juha at Mar 27, 2011 18:22

OK,

will get to it eventually.

Thanks

Jose

Posted by josep at Mar 27, 2011 18:30

Well,

I may have some incompatibility, as after following the steps i get an exception like this:

correcaminos:bin josep$ sh openremote.sh run
Using CATALINA_BASE: /Users/josep/Develop/openremote (trunk)/Runtime/apache-tomcat-6.0.18
Using CATALINA_HOME: /Users/josep/Develop/openremote (trunk)/Runtime/apache-tomcat-6.0.18
Using CATALINA_TMPDIR: /Users/josep/Develop/openremote (trunk)/Runtime/apache-tomcat-6.0.18/temp
Using JRE_HOME: /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
Exception in thread "main" java.lang.NoClassDefFoundError: (trunk)/Runtime/apache-tomcat-6/0/18/webapps/controller/WEB-INF/lib/native
Caused by: java.lang.ClassNotFoundException: (trunk).Runtime.apache-tomcat-6.0.18.webapps.controller.WEB-INF.lib.native
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

Any obvious thing you think I am doing wrong?

Posted by josep at Mar 28, 2011 00:21

At a guess Josep it looks like you might not have the full JDK installed on your box; not sure what distro you're running but make sure you install full jdk from the repositories (think it's java-1.6...), on debian: -

sudo apt-cache search java

Hope this helps,

Rich

Posted by kurrazyman at Mar 28, 2011 12:53

Thanks Richard,

I am running this on MacosX snow leopard, with the stock JRE. It is enough to run
the openremote binaries, and to build (apparently), but does not seem enough to run the build controller.

I will try and download a full JDK

Regards,

Josep

Posted by josep at Mar 28, 2011 15:29

Well,

the jdk is already installed in my system, it turns out, so this may not be the reason.

Juha, I seem to remember reading somewhere around here that you worked on a Snow Leopard system. I will appreciate any hints you may have as to what may be wrong.

Thanks,

josep

Posted by josep at Mar 28, 2011 16:50

Yeah I do. Try without the whitespace and (trunk) in the path, and see if that helps.

Posted by juha at Mar 28, 2011 18:37

This did it, thanks.

Posted by josep at Mar 28, 2011 19:21

OK,

well, the change was easy enough, as suspected. However, I uncovered a few other difficulties, like the wrong conversion from a signed byte to its unsigned equivalent (in Unsigned8bit.java, which was originally giving me an exception), and, then, finally, total unresponsiveness from the slider, with some funny behavior (read ahead)

Looking at the logs, what I believe I have seen is this: I can set the dimmed light to maximum (via a dedicated button, there to test). Afterwards, I can read the status level from the right group address, however this does not seem to affect the slider position, which remains at 0.

When I try to use the slider, apparently it sends the "0" value to the group address which sets the scale/dim, taking the dimmed light to obscurity... As the slider does not respond to the touch gesture (I am using an iPod touch), it remains at 0 all the time, and it can only send a "0" as the value to be set...

Sooo...

Has the slider feature been tested on KNX? if not on KNX, has it been tested on anything else? I would like to know, to have more data trying to figure out why the slider does not seem to respond.

Regards,

josep

Posted by josep at Mar 28, 2011 22:53

Hi Josep,

I have seen similar issues before and I believe it occurs because the your composer account has got itself into trouble and your controller.xml and panel.xml are out of sync. There are other discussions about this on the forum and I believe Juha can sort this out for you. I have resorted to making a new designer account before or try removing all the devices, commands, sensors and screens from your existing account and then start again.

Rich

Posted by kurrazyman at Mar 29, 2011 07:12

Thanks for the hint.

Well, I sanitized and simplified fully my project. Did not have to go back to the designer, as the XML format seems simple enough.

I had gestures which were interfering with the "slider gesture". Got rid of them. No behavior change.
I had spurious buttons, remnants fo defunct decisions in the designer. Got rid of them. No behavior change.
I eliminated everything, except having ONe group with ONE screen with ONE slider, and the corresponding sensor, and commands. No behavior change.

Using directly restful calls from my browser I can set the dimmer, and get the state, but the slider on the ipod GUI does not work for me (it does not move, only seems to send writes of zeroes to the dimmer)

So, in sum, at this point I am ready to believe something is wrong with the iphone panel.

For reference I am including the simplified controler.xml and panel.xml files I am using, just in case I got them wrong, and that explains the effects.

Regards,

Josep

controller.xml:

<?xml version="1.0" encoding="UTF-8"?>
<openremote xmlns="http://www.openremote.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openremote.org http://www.openremote.org/schemas/controller.xsd">
  <components>
    <slider id="77">
      <setValue>
        <include type="command" ref="253" />
      </setValue>
      <include type="sensor" ref="238" />
    </slider>
  </components>
  <sensors>
    <sensor id="238" name="Salon Mesa Nivel" type="level">
      <include type="command" ref="257" />
    </sensor>
  </sensors>
  <commands>
    <command id="253" protocol="knx">
      <property name="command" value="scale" />
      <property name="groupAddress" value="2/0/9" />
      <property name="DPT" value="5.001" />
    </command>

    <command id="257" protocol="knx">
      <property name="command" value="status" />
      <property name="groupAddress" value="2/0/2" />
      <property name="DPT" value="5.001" />
    </command>
  </commands>
  <config>
    <property name="controller.roundrobin.tcpserver.port" value="20000" />
    <property name="multicast.address" value="224.0.1.100" />
    <property name="controller.roundrobin.multicast.port" value="10000" />
    <property name="multicast.port" value="3333" />
    <property name="controller.groupname" value="floor20" />
    <property name="Macro.IR.Execution.Delay" value="500" />
    <property name="controller.roundrobin.multicast.address" value="224.0.1.200" />
    <property name="lircd.conf.path" value="/etc/lircd.conf" />
    <property name="controller.groupmember.autodetect.on" value="true" />
    <property name="webapp.port" value="8080" />
    <property name="copy.lircd.conf.on" value="true" />
    <property name="irsend.path" value="/usr/local/bin/irsend" />
    <property name="resource.upload.enable" value="true" />
    <property name="controller.applicationname" value="controller" />
  </config>
</openremote>


panel.xml:

<?xml version="1.0" encoding="UTF-8"?>
<openremote xmlns="http://www.openremote.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openremote.org http://www.openremote.org/schemas/panel.xsd">
  <panels>
    <panel id="1" name="Seattle">
      <include type="group" ref="140" />
    </panel>
  </panels>
  <screens>
    <screen id="40" name="Comedor">
      <absolute left="55" top="40" width="198" height="44">
        <slider id="77" vertical="false" passive="false">
          <link type="sensor" ref="238" />
        </slider>
      </absolute>
    </screen>
  </screens>
  <groups>
    <group id="140" name="Salon">
      <include type="screen" ref="40" />
    </group>
  </groups>
</openremote>

Posted by josep at Mar 29, 2011 08:07

Juha,

can you take a look at the xmls in my last post, let me know if you think they are correct.

I cannot test with anything but an iPod (I am not sure how to set up the web interface), so I do not know if this is a problem of the controller
or of the panel. It seems to me like the panel is the one to blame.

Thanks,

Josep

Posted by josep at Mar 29, 2011 16:40

Yep, thanks.

Eric will track down the slider issue on iOS panel.

Posted by juha at Mar 29, 2011 17:43

OK,

I will check-in my small fixes, so that he can better track the issue.

Regards,

Josep

Posted by josep at Mar 29, 2011 18:20

Obviously, if you're able to track it down on your own, please feel free to continue to do so. The more eye-balls the better. One of the benefits of Open Source

If you do find issues, or produce a patch, we'll be more than happy to apply it and produce a bug-fox release.

Posted by juha at Mar 29, 2011 19:43

Well,

I have fixed two issues, and, as I told you in a sourceforge email, was getting ready to check-in the modified sourcefiles (two of them) using svn, as
you suggested in an earlier post, however I need to be added to the project by the admin (you) in order to do so.

These modifications fix the problem I started discussing in this thread, plus a related one I found later. The solution is easier than what I suggested initially. The related problem is related with the signed nature of integers in Java, and the fact that the constructor for Unsigned8bit did not take proper care of this.

Else, let me know how you want me to send you the modifications.

Josep

Posted by josep at Mar 29, 2011 19:49

Ok, I may have missed the email from SF (nothing popped out from my INBOX on a quick glance at least).

Sounds like they're small patches so feel free to email me the 'svn diff' output and I will apply them, please send to juha at openremote org

Thanks!

Posted by juha at Mar 29, 2011 19:53

Eric reports the issue may be due to a missing <min> and <max> elements in panel.xml for slider – iOS code expects them to be present, but current iteration of modeler does not add them – mismatch between controller which does not require <min> and <max> for 'LEVEL' type of sensors (range 0-100 is implied) but does always require them for custom 'range' sensors, whereas iOS panel expects them always for slider components regardless of sensor type they're bound to (as per the panel XML schema).

Quick fix is to add them manually to your panel.xml until online designer is fixed to produce correct XML document instances that adhere to the schema. Eric will also provide a patch for iOS which defaults the slider min-max values to 0-100 if no XML elements are present in panel.xml

Posted by juha at Mar 30, 2011 16:53

OK, thanks.

That makes sense.
I will act on Panel.xml, it has a simple format.

Jose

Posted by josep at Mar 31, 2011 16:14

Hello Josep,

If you read this post before my edit, just forget what I said.
Indeed, adding a min/max element to the slider in panel.xml did fix the issue for me.
My slider definition now looks like this:
<slider id="30" vertical="false" passive="false">
<link type="sensor" ref="36" />
<min value="0"/>
<max value="100"/>
</slider>

Eric

Posted by ebariaux at Mar 31, 2011 19:29

I also committed a quick fix that sets the sliders min/max to 0/100 if no value is present in the panel.xml file.
This is on the branches/project/iPad_Console_2_0_0_Betas branch in svn.

Posted by ebariaux at Mar 31, 2011 20:24

Thanks Eric,

I tried setting the range explicitly and that works fine,..., except for a slight strangeness which you may be able to "fix".

The dimmer I have has slow action, that is, it takes a while to reach the goal level set, so it creates a "nice" sense of progression.

The problem with the sensors the way they are right now is that they read info from the level group, and what they get is, of course, not yet the target value set. The result is that the slider in the UI jumps to another position jerking to the goal position as it gets values from the bus. The effect is strange... (I do not know how to fix this, other than to provide some "hosteresis" right after the slider is moved by the user, so that it allows the dimmer to settle.

Another problem I have detected is that when there is a gesture on the screen, moving along the same edge as the slider, moving the slider can set off the gesture... two for the price of one

I am not sure how easy/difficult it is to allow the gestures only outside problematic areas (like sliders). It certainly seems easier to forbid gestures on screens with sliders, so that this effect does not happen.

Thanks,

Josep

Posted by josep at Mar 31, 2011 23:29

Similar gesture behaviour is exhibited on the Android panels as well, when you try and adjust the slider too quickly the screen change gesture overrules it and you suddenly change screens and then slider value goes back to how it was before the action.

Posted by kurrazyman at Apr 01, 2011 07:17

Hi Josep,

Sorry for the late reply.
I'll take a look at both issues and see how I can improve that.

Eric

Posted by ebariaux at Apr 04, 2011 18:14
Document generated by Confluence on Jun 05, 2016 09:31