Ankündigung

Einklappen
Keine Ankündigung bisher.

Switch light on when UDP command received from PC

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #16
    Perry,

    just to be sure: The receiving (listening port) of the EibPC is 4806 but this does not mean that the sending port is 4806 as well.

    The Port and IP in
    [highlight=epc] if event(readudp(Port, IP,Data1)) then ... [/highlight]
    are those of the sending partner.

    Regards
    Bernd

    Kommentar


      #17
      OK, thanks to both of you for the explanation, I understand the port-thing a little better and got the process working. For testing, I am skipping the port and IP conditions altogether, allowing me to test by sending UDP commands from multiple PC's.

      I have moved on to the example that enertegus provided to the request from TheMax74. I am very interested in being able to enter a regular 'KNX type address' and a value of 0 or 1 as UDP command to switch the address off or on.

      However, when I try th code that was provided:

      Code:
      IP=0u32
      Port=0u16
      Rx=$$ // Received Command, for example 0/0/1=1
      telegram=event(readudp(Port, IP, Rx));
      // Group address send as 16-Bit Number
      GA_Nr=convert(split(Rx,0u16,find(Rx,$=$,0u16)-1u16), 0u16);
      // Must fit the GA Type, e.g. 8 Bit:
      Value=convert(split(Rx,find(Rx,$=$,0u16),1399u16),0u08)
           
      if telegram then {
          write(address(GA_Nr),Value)
      }endif
      and send the UDP command:

      2/2/0=1

      , the debugger shows this:

      Query Value of Object 548 (GA_Nr):
      C:/Users/Perry/Documents/KNX/Enertex producten/EIBstudio/EibStudio-win/EibstudioData/nconf -q 548 192.168.1.35
      Value of Object 548: 00 02 00 00 {2013-08-26 11:25:12}
      Typ: positive Ganzzahl
      Value: 2

      If I use a non-existing 'address' like 11/203/3, the debugger result is 11.

      I have noticed that, if I just send regular values like 1 or 2 or 11203, the debuggers shows the same values as a result. However, when I send a value of six figures, for instance 112033, the result is value 46497.

      So it appears that, instead of splitting the left side of the = of the UDP command to a x/x/x value, it is using just the first value before the slash (with a maximum of 5 digits, beyond which it is re-calculating to another value).

      Kommentar


        #18
        I have not yet my Eibpc to test, but the Group address should be sent as 16bit number.
        This comment
        Rx=$$ // Received Command, for example 0/0/1=1
        is not correct anymore.
        It should be, for example, 13123=1
        Code:
        The Number is calculated as address= [main group] x 2048+[middle group] x 256 + [subgroup]. As an example with  
        [main group]=5, [middle group]=3 and [subgroup]=11 the telegramm imaga of '5/3/11' is addressed. You have to cal-
        culate this number by yourself  or you can use the function getaddress.
        Cit. the user manual (English) at page 188.

        Kommentar


          #19
          Hi,

          Massimo is right
          Zitat von TheMax74 Beitrag anzeigen
          Group address should be sent as 16bit number.
          [highlight=epc]
          ///////////////////////////////////////////////////////////////////////////////
          //
          // a simple EibPC command line interface via UDP
          //
          ///////////////////////////////////////////////////////////////////////////////
          //
          // Usage:
          //
          // First: include the macro.
          // Second: the macro answers you commands. So you need two instances
          // of netcat, one to send commands and another to listen to the response
          //
          // Listening:
          // netcat -l -u -p OutPort OutIP
          //
          // to send a command line start netcat like
          // "netcat RemoteIP 4806 -p /RemotePort/ on computer with RemoteIP"
          // if you omit RemoteIP and leave it zero then all IP will be accepted

          :begin UDPCommandInterface( RemotePort, RemoteIP, Password, TimeOut, OutPort, OutIP )
          :info $provides functionality to send command via UDP to the EibPC$ \\
          $RemotePort - the port the command uses to send lines$\\
          $RemoteIP - if not zero then only accept packets from this IP $\\
          $Password - needs to be sent to enable the interface$\\
          $TimeOut - time in milliseconds after which the command interface will be password secured again$\\
          $OutPort - this port will receive answer packets$\\
          $OutIP - this is the accepting computer, normally the same as RemoteIP$
          :shortinfo $provides functionality to send command via UDP to the EibPC$

          UDPCI_Port = OutPort
          UDPCI_IP = OutIP

          UDPCI_ReadPort=0u16
          UDPCI_ReadIP=0u32
          UDPCI_UDPBuffer=$$
          UDPCI_Buffer = $$
          UDPCI_Commandline = $$
          UDPCI_Command = $$
          UDPCI_posLF = 0u16
          UDPResponse = $$


          UDPCI_HG = $$; UDPCI_MG = $$; UDPCI_UG = $$
          UDPCI_GA = 2218u16
          UDPCI_Type = $$; // b01, b04, u08, u16, u32, s16, s32, f16, f32, s, s14
          UDPCI_Value = $$
          password = $1234$
          UDPCI_Enabled = EIN; //
          UDPCI_pos1 = 0u16
          UDPCI_pos2 = 0u16
          UDPCI_posCR = 0u16

          UDPCI_EnableResponseWait = AUS;
          NewData = AUS;

          if event(readudp(UDPCI_ReadPort, UDPCI_ReadIP, UDPCI_UDPBuffer)) and (UDPCI_ReadPort==RemotePort) and ((RemoteIP == 0u32) or (UDPCI_ReadIP==RemoteIP)) or \\
          ( after(change(UDPCI_Buffer),1u64) and size( UDPCI_Buffer ) > 0u16 ) then {
          UDPResponse = $$; /* clear response string */
          if (UDPCI_ReadPort==RemotePort) and ((RemoteIP == 0u32) or (UDPCI_ReadIP==RemoteIP)) then {
          UDPCI_Buffer = UDPCI_Buffer + UDPCI_UDPBuffer;
          UDPCI_UDPBuffer = $$;
          } endif;
          sendudp( OutPort, OutIP, $Received UDP Packet for EibPC Command Line Interface$+UDPCI_Buffer, 13, 10 );
          UDPCI_posCR = find( UDPCI_Buffer, CR, 0u16);
          if UDPCI_posCR == 0u16 then UDPCI_Buffer = split( UDPCI_Buffer, 1u16, END) endif;

          UDPCI_posLF = find( UDPCI_Buffer, LF, 0u16);
          if UDPCI_posLF == 0u16 then UDPCI_Buffer = split( UDPCI_Buffer, 1u16, END) endif;

          if UDPCI_posLF > 0u16 and UDPCI_posLF < EOS then {
          UDPCI_Commandline = split( UDPCI_Buffer, 0u16, UDPCI_posLF );
          UDPCI_Buffer = split( UDPCI_Buffer, UDPCI_posLF+1u16, END );

          UDPCI_Command = split( UDPCI_Commandline, 0u16, 0u16 );
          if UDPCI_Command == $p$ then {
          UDPCI_Value = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 0u16 )+1u16, size( UDPCI_Commandline )-2u16 );
          UDPCI_Enabled = (UDPCI_Value == password);
          if UDPCI_Enabled then sendudp( OutPort, OutIP, $Password was given, accepting now other commands$, 13, 10 ) endif;
          if !UDPCI_Enabled then sendudp( OutPort, OutIP, $Passwor was wrong, accepting no other commands$, 13, 10 ) endif;
          UDPCI_EnableResponseWait = AUS;
          } endif;

          // if the remanent variables macro is included we may use the following code to dump all remanent variables
          #ifndef NO_RV
          if UDPCI_Command == $d$ then {
          sendudp( OutPort, OutIP, $Dumping all remanent variables$, 13, 10 );
          sendudp( OutPort, OutIP, $------------------------------------------------------------------------$, 13, 10 );
          RV_DoDump2UDP = EIN; /* The remanent variables macro defines this variable */;
          } endif;

          if UDPCI_Command == $s$ then {
          RV_SetVariableNumberOrName = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 0u16 )+1u16, find( UDPCI_Commandline, SPACE, 1u16 )-1u16 );
          UDPCI_pos1 = find(UDPCI_Commandline, SPACE, 1u16 );
          UDPCI_pos2 = find(UDPCI_Commandline, LF, 0u16 );
          if UDPCI_pos2 > UDPCI_pos1+1u16 then RV_SetVariableString = split( UDPCI_Commandline, UDPCI_pos1+1u16, UDPCI_pos2-1u16) \\
          else RV_SetVariableString = EMPTYSTRING endif;
          } endif;
          #endif
          if UDPCI_Command == $h$ or UDPCI_Command == $?$ then {
          UDPResponse = $list of commands for the EibPC Command Line Interface$ + CRLF;
          UDPResponse = UDPResponse + $-----------------------------------------------------------------------------------------$ + CRLF;
          UDPResponse = UDPResponse + $h or ? --> help as displayed$ + CRLF;
          UDPResponse = UDPResponse + $p password --> send the password, if timeout occurs the password will be reset$ + CRLF;
          UDPResponse = UDPResponse + $w HG MG UG Type Value --> write a value to the bus$ + CRLF;
          UDPResponse = UDPResponse + $ HG MG UG: parts of the GA like HG/MG/UG$ + CRLF;
          UDPResponse = UDPResponse + $ Type as one of b, u08, u16, u32, s08, s16, s32, f16, f32, s$ + CRLF;
          UDPResponse = UDPResponse + $ Value as the actual value$ + CRLF;
          UDPResponse = UDPResponse + $R HG MG UG --> read a value from the bus$ + CRLF;
          UDPResponse = UDPResponse + $r HG MG UG --> read a value from the EibpC$ + CRLF;
          #ifndef NO_RV
          UDPResponse = UDPResponse + $d --> dump all remanent variables$ + CRLF;
          UDPResponse = UDPResponse + $s number Value --> set a value to a remanent variable, the number is given with dump and may change after new compilation$ + CRLF;
          UDPResponse = UDPResponse + $s VariableName Value --> set a value to a remanent variable, the Variable Name is given with dump (will not change)$ + CRLF;
          #endif
          UDPResponse = UDPResponse + $-----------------------------------------------------------------------------------------$ + CRLF;
          sendudp( OutPort, OutIP, UDPResponse );
          } endif;

          if UDPCI_Command == $w$ and UDPCI_Enabled then {
          UDPCI_pos1 = find (UDPCI_Commandline, SPACE, 4u16 );
          UDPCI_HG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 0u16 )+1u16, find( UDPCI_Commandline, SPACE, 1u16 )-1u16 );
          UDPCI_MG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 1u16 )+1u16, find( UDPCI_Commandline, SPACE, 2u16 )-1u16 );
          UDPCI_UG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 2u16 )+1u16, find( UDPCI_Commandline, SPACE, 3u16 )-1u16 );
          UDPCI_GA = convert( UDPCI_HG, 0u16) * 2048u16 + convert( UDPCI_MG, 0u16) * 256u16 + convert( UDPCI_UG, 0u16);
          UDPCI_Type = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 3u16 )+1u16, find( UDPCI_Commandline, SPACE, 4u16 )-1u16 );
          UDPCI_Value = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 4u16 )+1u16, size(UDPCI_Commandline)-2u16 );
          sendudp( OutPort, OutIP, $witing $+UDPCI_Value+$ to $+UDPCI_HG+$/$+UDPCI_MG+$/$+UDPCI_UG+$($+convert(UDPCI_GA,$$)+$) as $+UDPCI_Type, 13, 10 );
          if find( UDPCI_Type, $b$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0b01) ) endif;
          if find( UDPCI_Type, $u08$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0u08) ) endif;
          if find( UDPCI_Type, $u16$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0u16) ) endif;
          if find( UDPCI_Type, $u32$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0u32) ) endif;
          if find( UDPCI_Type, $s08$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0s16) ) endif;
          if find( UDPCI_Type, $s16$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0s16) ) endif;
          if find( UDPCI_Type, $s32$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0s32) ) endif;
          if find( UDPCI_Type, $f16$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0f16) ) endif;
          if find( UDPCI_Type, $f32$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, 0f32) ) endif;
          if find( UDPCI_Type, $s$, 0u16 ) < END then write( address( UDPCI_GA ), convert( UDPCI_Value, $$c14)) endif;
          UDPCI_EnableResponseWait = AUS;
          } endif;

          if UDPCI_Command == $R$ and UDPCI_Enabled then {
          sendudp( OutPort, OutIP, $Read request detected$, 13, 10 );
          UDPCI_HG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 0u16 )+1u16, find( UDPCI_Commandline, SPACE, 1u16 )-1u16 );
          UDPCI_MG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 1u16 )+1u16, find( UDPCI_Commandline, SPACE, 2u16 )-1u16 );
          UDPCI_UG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 2u16 )+1u16, END);
          UDPCI_GA = convert( UDPCI_HG, 0u16) * 2048u16 + convert( UDPCI_MG, 0u16) * 256u16 + convert( UDPCI_UG, 0u16);
          if UDPCI_GA != 0u16 then {
          read( address( UDPCI_GA ));
          UDPCI_EnableResponseWait = EIN;
          } else {
          UDPCI_EnableResponseWait = AUS;
          } endif;
          } endif;

          if UDPCI_Command == $r$ and UDPCI_Enabled then {
          sendudp( OutPort, OutIP, $read request detected$, 13, 10 );
          UDPCI_HG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 0u16 )+1u16, find( UDPCI_Commandline, SPACE, 1u16 )-1u16 );
          UDPCI_MG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 1u16 )+1u16, find( UDPCI_Commandline, SPACE, 2u16 )-1u16 );
          UDPCI_UG = split( UDPCI_Commandline, find( UDPCI_Commandline, SPACE, 2u16 )+1u16, END);
          UDPCI_GA = convert( UDPCI_HG, 0u16) * 2048u16 + convert( UDPCI_MG, 0u16) * 256u16 + convert( UDPCI_UG, 0u16);
          if UDPCI_GA != 0u16 then {
          sendudp( OutPort, OutIP, $event detected to $+UDPCI_HG+$/$+UDPCI_MG+$/$+UDPCI_UG+$($+convert(UDPCI_GA,$$)+$) UDPCI_Value: $+convert( gaimage(UDPCI_GA),$$), 13, 10 );
          } endif;
          } endif;
          } endif;
          } endif


          // if event( address( UDPCI_GA ) ) and UDPCI_EnableResponseWait then {
          // sendudp( OutPort, OutIP, $response detected to $+UDPCI_HG+$/$+UDPCI_MG+$/$+UDPCI_UG+$($+convert(UDPCI_GA,$$)+$) UDPCI_Value: $+convert( gaimage(address( UDPCI_GA )),$$), 13, 10 )
          //} endif;

          KNXGA = 0u16
          KNXBuffer = $$

          if event( readknx( KNXGA, KNXBuffer ) ) and KNXGA == UDPCI_GA and UDPCI_EnableResponseWait then {
          sendudp( OutPort, OutIP, $event detected to $+UDPCI_HG+$/$+UDPCI_MG+$/$+UDPCI_UG+$($+convert(UDPCI_GA,$$)+$) UDPCI_Value: $+convert( KNXBuffer,$$), 13, 10 )
          } endif;

          if event( readknx( KNXGA, KNXBuffer ) ) and KNXGA == UDPCI_GA and UDPCI_EnableResponseWait then {
          sendudp( OutPort, OutIP, $response detected to $+UDPCI_HG+$/$+UDPCI_MG+$/$+UDPCI_UG+$($+convert(UDPCI_GA,$$)+$) UDPCI_Value: $+convert( KNXBuffer,$$), 13, 10 )
          } endif;


          :return AUS
          :end
          [/highlight]

          You might not be able to use the above macro at once because it's an excerpt from the above mentioned Macro collection but it shows how this all can work.

          Regards,
          Bernd

          Kommentar


            #20
            Thanks, that was the solution, together with a change of the type of value to binary.
            In conclusion, the following code switches on a light with address 2/2/0 by sending an UDP command of 4608=1 to port 4806:

            Code:
            IP=0u32
            Port=0u16
            Rx=$$ // Received Command, for example 2/2/0=1 -> the KNX address must be entered as (2x2048+2x256+0=): 4608
            telegram=event(readudp(Port, IP, Rx));
            // Group address send as 16-Bit Number
            GA_Nr=convert(split(Rx,0u16,find(Rx,$=$,0u16)-1u16), 0u16);
            // Must fit the GA Type, for On and OFF type we need binary type 0b01:
            Value=convert(split(Rx,find(Rx,$=$,0u16),1399u16),0b01)
                 
            if telegram then {
                write(address(GA_Nr),Value)
            }endif
            Thanks to all of you for your kind help and patience!!

            Kommentar


              #21
              Unfortunately, it turns out I can switch ON the light, but I can not switch off the light by sending UDP command 4608=0
              So I need one more bit of help to get all the way to the finish...

              Kommentar


                #22
                This is driving me crazy: why is it that with the code
                Value=convert(split(Rx,find(Rx,$=$,0u16),1399u16), 0b01)

                and sending UDP command "4099=0"

                The debugger shows as the value for variable Value "ON" (this is the same as when when sending "4099=1")?

                Kommentar


                  #23
                  break
                  [highlight=epc]Value=convert(split(Rx,find(Rx,$=$,0u16),1399u16), 0b01) [/highlight] up into smaller pieces easier to debug.

                  [highlight=epc]
                  Lastrx = $$
                  if change(Rx) then {
                  Lastrx = Rx
                  PosEqual = find(Rx,$=$,0u16);
                  /* find returns 1400 if text is not found */;
                  SplitString = split(Rx, PosEqual,1399u16);
                  Value=convert( SplitString, 0b01);
                  } endif
                  [/highlight]

                  What do you get now? (And keep in mind that values might change from one cyclus to the next, thus giving you results you do not expect. Rx will probably be empty the next turn...

                  Regards,
                  Bernd

                  Kommentar


                    #24
                    Thanks Bernd for trying to solve this seemingly simple issue.
                    I replaced with the following code, but when compiling I get a syntax error already in the first line:
                    if change(Rx) then {

                    I don't see what the problem is here? Error message below:

                    Syntax error in line:[27]
                    >if change(Rx) then { Lastrx = Rx PosEqual = find(Rx,$=$,0u16); /* find returns 1400 if text is not found */; SplitString = split(Rx, PosEqual,1399u16); Value=convert( SplitString, 0b01);} endif < in file "C:/Users/Perry/Documents/KNX/Enertex producten/EIBstudio/EibStudio-win/EibstudioData/tmpApp.txt"
                    Valid until column position: {0}
                    STOP Parser --> if change(Rx) then { Lastrx = Rx PosEqual = find(Rx,$=$,0u16); /* find returns 1400 if text is not found */; SplitString = split(Rx, PosEqual,1399u16); Value=convert( SplitString, 0b01);} endif


                    ID:4
                    EibParser ended with an error

                    %

                    Code used:
                    Code:
                    [EibPC]
                    #include C:/Users/Perry/Documents/KNX/Enertex producten/EIBstudio/EibStudio-win/EibstudioData/VA_EibPC.epc
                    
                    IP=0u32
                    Port=0u16
                    Lastrx = $$
                    Rx=$$ // Received Command, for example 0/0/1=1
                    telegram=event(readudp(Port, IP, Rx));
                    // Group address send as 16-Bit Number
                    GA_Nr=convert(split(Rx,0u16,find(Rx,$=$,0u16)-1u16), 0u16);
                    // Must fit the GA Type, e.g. 8 Bit:
                    
                    if change(Rx) then {
                        Lastrx = Rx
                        PosEqual = find(Rx,$=$,0u16);
                        /* find returns 1400 if text is not found */;
                        SplitString = split(Rx, PosEqual,1399u16);
                        Value=convert( SplitString,  0b01);
                    } endif 
                    
                         
                    if telegram then {
                        write(address(GA_Nr),Value)
                    }endif

                    Kommentar


                      #25
                      Lastrx = Rx;

                      Kommentar


                        #26
                        Good find!

                        Next error:
                        Runtime error:
                        ! variable not defined: >PosEqual< !
                        ID:11

                        I guess this means that this needs to be listed on top of the code with the proper associated data Types:
                        So what types should these new variables be given?:

                        PosEqual
                        SplitString
                        Value

                        Kommentar


                          #27
                          PosEqual = 0u16 // must be the result type of find() function

                          SplitString = $$ // obviously a string

                          Value = AUS // you want a boolean? you have to define a boolean!
                          If you need other types like dimmer value or the like you will nee different conversion function convert( SplitString, ????)

                          Kommentar


                            #28
                            I don't know how I could have overlooked this, but it turned out that the split of the string on the right side of the equal-sign lacked a '+1u16'. This meant that in the original proposed code the equal-sign was included in the selection and did not produce desired results. Below the code that works:

                            Code:
                            IP=0u32
                            Port=0u16
                            Rx=$$ // Received Command, for example 0/0/1=1
                            telegram=event(readudp(Port, IP, Rx));
                            // Group address send as 16-Bit Number
                            GA_Nr=convert(split(Rx,0u16,find(Rx,$=$,0u16)-1u16), 0u16);
                            // Must fit the GA Type, e.g. 8 Bit:
                            Value=convert(split(Rx,find(Rx,$=$,0u16)+1u16,1399u16),0b01)
                                 
                            if telegram then {
                                write(address(GA_Nr),Value)
                            }endif

                            Kommentar


                              #29
                              Now that this is solved for "ON and OFF" situations, I would like to make it possible to use the same code for percentage types, so I can set the dimmer values for lights.

                              Therefore, I would like to be able to count the length of variable "Value" and, if it is 1 digit, convert the data type to 0b01 and if it is 2 digits, it should be converted to 0u08.


                              I have looked in the manual, but could not find a command that counts the length of a variable (the manual does have a command for counting the size of a string: size(Rx) gives as a result 8 for UDP command 4099=1 and 9 for UDP command 4099=20).


                              I have tried the following:

                              Code:
                              temp=size(Rx)
                              if temp < 9 then {
                                  Value=convert(split(Rx,find(Rx,$=$,0u16)+1u16,1399u16),0b01)
                              }endif
                              
                              if temp > 8 then {
                                  Value=convert(split(Rx,find(Rx,$=$,0u16)+1u16,1399u16),0u08)
                              }endif
                              But I get the following error message:

                              File: "C:/Users/Perry/Documents/KNX/Enertex producten/EIBstudio/EibStudio-win/EibstudioData/tmpMacroOut.txt" has been written
                              Runtime error:
                              ! Make use of convert-functions:
                              Datatypes of parameters are not the same, please controll the return value, too. 1-th argument of : >temp<9< !
                              ID:14
                              EibParser ended with an error

                              Kommentar


                                #30
                                Try
                                [highlight=epc]
                                if temp < 9u16 then {
                                [/highlight]
                                Die Selbsthilfegruppe "UTF-8-Probleme" trifft sich diesmal abweichend im groüen Saal.

                                Kommentar

                                Lädt...
                                X