python-vxi11-server icon indicating copy to clipboard operation
python-vxi11-server copied to clipboard

vxi11_server

Open ChevalierLouis opened this issue 3 years ago • 29 comments

Hello I have this issue, but I have Installed the module

   import vxi11_server as Vxi11

ModuleNotFoundError:No module named 'vxi11_server'

I don't know how to fix it

Thanks (for your woks this can help me)

ChevalierLouis avatar Apr 30 '21 09:04 ChevalierLouis

Hi, There is no need to install this library.

  • Simply clone it onto your machine
  • cd into the demo_servers folder and run the example server.
  • open a second shell and run the example client.

Give that a shot and lets see what happens. c.

coburnw avatar Apr 30 '21 18:04 coburnw

Hello 👋 back again

So the server run, but the client have an error Traceback (most recent call last): File "time_client.py", Line 1, in Import vxi11 ModuleNotFoundError:No module named 'vxi11'

ChevalierLouis avatar Apr 30 '21 19:04 ChevalierLouis

the example clients that come with this library are written for the python-vxi11 client library.

Go to https://github.com/python-ivi/python-vxi11 and follow the instructions there to install the client library. If you have another client library (such as national instruments) then you need to follow their instructions.

Have you had success communicating with an existing device using vxi11?

One step at a time. Good luck, c.

coburnw avatar Apr 30 '21 20:04 coburnw

Just a question is it possible to control Raspberry Pi GPIOs ? How can I do that ? Something like default_instr.write('pin1:on') but have success to communicating

Louis.

ChevalierLouis avatar May 03 '21 07:05 ChevalierLouis

Here is where i would start on this project.

  1. Come up with a command syntax. Following your suggestion:
    • 'set:pin.x:state'
    • 'get:pin.x'
    • and so forth.
  2. On the raspberry pi, copy time-device.py to gpio-device.py and edit:
    • in device_init() open the gpio library
    • in device_write() parse the command syntax and act on it.
    • in device_read() return results from the device_write()
  3. On the client computer, copy time-client.py to gpio-client.py and edit:
    • my_instr.write('set:pin.1:on')
    • my_instr.write('get:pin.1')
    • pin1_state = my_instr.read()

If you like, you might open a repository in your github account for a barebones vxi11 gpio device, then I might be able to offer more focused suggestions.

coburnw avatar May 03 '21 18:05 coburnw

Hello this is what I've done for now https://github.com/ChevalierLouis/vxi11-gpio-device

ChevalierLouis avatar May 04 '21 07:05 ChevalierLouis

Very Nice.

To be clear, you have a functioning requests/flask pair that you would like to replace with a vxi client/server pair?

If so, i would start on the client side by factoring out all the requests functionality into a class or module called, say, remote_gpio_requests.py making every effort to maintain functionality. Copy that to remote_gpio_vxi11.py and replace the requests logic with vxi11 logic. You can then switch between flask or vxi11 or the next-big-thing with hopefully just an import change.

On the server side, i would start a new project (they both could run concurrently) using time_device.py as boilerplate.

You've got a lot of good work there. You should reuse as much of it as you can.

coburnw avatar May 04 '21 17:05 coburnw

Yes it's what I would like to replace requests/flask with vxi, in fact this is my 2nd or 3rd program in python usually I use arduino esp, I write code in c++ since 2014. For me python have similarities, but classes in python is really abstract for me.

For the client part this will be really easy but the server I don't know how to make the thing who understands the "request" instr.write('*the command?'). I've tried to add a def something(self, other things.): in vxi11.py but no results (errors everywhere)

Thanks to help me(sorry for my English).

ChevalierLouis avatar May 04 '21 18:05 ChevalierLouis

referring to 'class TimeDevice(Vxi11.InstrumentDevice)' in the time-device.py example, TimeDevice() is the custom class the developer creates to manage communication with his device (yours might be named GpioDevice()). It extends a Vxi11.InstrumentDevice which means that python imports every function found in InstrumentDevice into the TimeDevice class, for better or for worse.

Contained in the library's instrument_device.py is the InstrumentDevice class itself. When the instrument server receives rpc's from the client it parses them and asks python to call the appropriate function in InstrumentDevice. Since TimeDevice extended the InstrumentDevice, Python first looks in TimeDevice for that function and calls it if it exists. If not, the function in the base class, InstrumentDevice, is called. Since TimeDevice overrides device_read(), it is the TimeDevice device_read() that is called. Since TimeDevice does not override device_write(), it is the InstrumentDevice device_write() that is called.

So to proceed, you might try copy & paste the device_write(...) function from the InstrumentDevice class into your copy of TimeDevice, and replace the code in the final else with your action returning err_no_error. To be clear, there should be no need to modify the library itself, bugs not withstanding.... Override only the functions you need in your device class.

which vxi11 client library are you using?

Heres a thought: modify a clean version of the time device example pair, so that you write a timezone to the time device, and it returns the current time with that timezone applied. That should get you started and make the transition to gpio easy. Just be careful not to fall into the python time rabbit hole.

(sorry for my French ;-)

coburnw avatar May 04 '21 19:05 coburnw

I will try this tomorrow I am a bit tired. Thanks

ChevalierLouis avatar May 04 '21 20:05 ChevalierLouis

for the lib I use the one on the link from your read.me

ChevalierLouis avatar May 05 '21 06:05 ChevalierLouis

So I have made this and it works (what did you think?)

  def device_write(self, opaque_data, flags, io_timeout): # 11
   
    
    error = vxi11.ERR_NO_ERROR

    if False:
        error = vxi11.ERR_IO_TIMEOUT
    elif False:
        error = vxi11.ERR_IO_ERROR
    elif False:
        error = vxi11.ERR_ABORT
    else:
        error = vxi11.ERR_OPERATION_NOT_SUPPORTED
        
    print (opaque_data)#opaque_data type= byte
    b=opaque_data
    s=str(b,'UTF-8')#on converti en string

    #on recupere le pin 
    starta = s.find("set:pin.")+len("set:pin.")
    enda = s.find(":o")
    pinact = s[starta:enda]
    
    #on recupere l'etat 
    starts = s.find("set:pin."+pinact)+len("set:pin."+pinact)+1
    ends = len(s)
    pinstate = s[starts:ends]
    
    # On met a l'état bas
    # Pour chaque GPIOs du dictionaire:
    for pin in actuator:
        GPIO.output(actuator[pin], GPIO.LOW)
    
    # on change l'état pour l'actioneur demendé
    if pinstate == "on":
        GPIO.output(actuator[pinact], GPIO.HIGH)
        print(pinact+"  "+pinstate)
    if pinstate == "off":
        GPIO.output(actuator[pinact], GPIO.LOW)
        print(pinact+"  "+pinstate)
        
    for pin in actuator:
        status[pin] = GPIO.input(actuator[pin])
    print ("lecture des nouveaux etats des pins :")
    print (status)

    
    return error

but this work however it prints somme erros (who don't make crash the gui)

def command():
      send=str(v.get())
      if returnEntry() == "":
            time_instr = vxi11.Instrument("TCPIP::"+result+"::inst1::INSTR")
            time_instr.write('set:pin.E'+send+':on')
      else:
            time_instr = vxi11.Instrument("TCPIP::"+returnEntry()+"::inst1::INSTR")
            time_instr.write('set:pin.E'+send+':on')

ChevalierLouis avatar May 05 '21 08:05 ChevalierLouis

I have done it and it works correctly I will put it on my git there is some miner errors but it's fine

thanks a lot

ChevalierLouis avatar May 05 '21 13:05 ChevalierLouis

Hello back did you know if I can close an re-open the server just with code?

ChevalierLouis avatar May 10 '21 11:05 ChevalierLouis

Hi Louis

see if I get you right: if you close an instrument the instrument handler the server used for it will get deleted. if you reopen the instrument again the server instanciates a new instrument handler from your class. if you want to have persistent settings with your instrument, you have to either create a kind of "class registry dictionary" for them or use global variables.

bye Ulf

ulda avatar May 15 '21 07:05 ulda

hello back I have continue continue to work on it and i whant to improuve it : so I have make a device read :

def device_read(self, request_size, term_char, flags, io_timeout): #= 12
       "The device_read RPC is used to read data from the device to the controller"
       error = vxi11.ERR_NO_ERROR

      opaque_data = b""
      if False:
          error = vxi11.ERR_IO_TIMEOUT
      elif False:
          error = vxi11.ERR_IO_ERROR
      elif False:
          error = vxi11.ERR_ABORT
      else:
          error = vxi11.ERR_OPERATION_NOT_SUPPORTED
          
      for pin in actuator1:
          status1[pin] = GPIO.input(actuator1[pin])

      for pin in actuator2:
          status2[pin] = GPIO.input(actuator2[pin])

      data1=str(status1)
      data2=str(status2)
      opaque_data=data1.encode("ascii")
      print (opaque_data)

      reason = ReadRespReason.END
      result = error, reason, opaque_data
      return result

I have a problem with encoding

have a nice day

ChevalierLouis avatar Jun 01 '21 09:06 ChevalierLouis

Hi Louis,

Python isnt my first language. You need to help me out a bit... What problem are you having with the encoding?

coburnw avatar Jun 02 '21 16:06 coburnw

for me also this is my first real project with it .

like the time server I want to use device ready to send the gpio current state a take the result to do things

so I use for loops to read all my gpios

  for pin in actuator1:
      status1[pin] = GPIO.input(actuator1[pin])

  for pin in actuator2:
      status2[pin] = GPIO.input(actuator2[pin])

the values are in JSON(I think) so i convert them in String

  data1=str(status1)
  data2=str(status2)
  opaque_data=data1.encode("ascii") #then in ascii

to send them when device read is send

ChevalierLouis avatar Jun 02 '21 17:06 ChevalierLouis

This is what i think i see:

  1. You use a loop to build a dictonary of gpio input values
  2. convert the dictionary to a string
  3. encode the string to binary.

It seems that should work. Perhaps the problem is with the decoding on the application side? What error message are you getting, and is it on the client or server end?

Also of note: the ERR constants are prefixed with vxi11 while the ReadRespReason is not. It may or may not mater depending on how the imports are defined.

coburnw avatar Jun 02 '21 18:06 coburnw

I will tell you tomorrow because I am not in front of the pi

ChevalierLouis avatar Jun 02 '21 18:06 ChevalierLouis

This is the error

Traceback (most recent call last): File "C:\Users\louis\Desktop\atem\GUI+RPIS\atem widows GUI\test.py", line 318, in GPIO_instr.read() File "C:\Users\louis\AppData\Local\Programs\Python\Python39\lib\site-packages\vxi11\vxi11.py", line 731, in read return self.read_raw(num).decode(encoding).rstrip('\r\n') File "C:\Users\louis\AppData\Local\Programs\Python\Python39\lib\site-packages\vxi11\vxi11.py", line 701, in read_raw raise Vxi11Exception(error, 'read') vxi11.vxi11.Vxi11Exception: 8: Operation not supported [read]

but I don't knox how too fix it

ChevalierLouis avatar Jun 03 '21 06:06 ChevalierLouis

This is a simple one, I make a Quizz from it: What does you code return in the error variable if you reuse this code from the examples:

error = vxi11.ERR_NO_ERROR
if False:
      error = vxi11.ERR_IO_TIMEOUT
elif False:
      error = vxi11.ERR_IO_ERROR
elif False:
      error = vxi11.ERR_ABORT
else:
      error = vxi11.ERR_OPERATION_NOT_SUPPORTED

ulda avatar Jun 03 '21 06:06 ulda

I have this: image

ChevalierLouis avatar Jun 03 '21 07:06 ChevalierLouis

Louis, look at your server code of def device_read - as posted above -

your read() returns this error. or, in other words: after line 280 of your code, your errror variable holds vxi11.ERR_OPERATION_NOT_SUPPORTED

this way the client program will allways throw an error because you programmed it this way.

you have to adapt the example code (the thing with the if False..elif.. else) to fit your program flow or throw it away and return one of the mentioned error conditions as result of your device_read method. bye Ulf

ulda avatar Jun 03 '21 07:06 ulda

Thanks I will try it

ChevalierLouis avatar Jun 03 '21 15:06 ChevalierLouis

hello, i'm still working on the server but i have to change board. When I do an inst read it displays nothing

client: import vxi11

instr = vxi11.Instrument('TCPIP::192.168.1.36::inst1::INSTR')

state=instr.read()
print(state)

serveur:

          def device_read(self, request_size, term_char, flags, io_timeout): #= 12
              "The device_read RPC is used to read data from the device to the controller"                                         
              error = vxi11.ERR_NO_ERROR                                                                                              
              opaque_data = b""                                                       
                                                                             
                                                                               
              for pin, id in actuator.items():                                                                                        
                  cmd ='gpioget '+ id                      
                  status =os.system(cmd)                                 
              states=str(status)                                                                                                   
                                                                         
              oapque_data=bytes(states,'ascii')#I try assci utf-8 ....                                                                                       
              print(oapque_data)                                                                                                   
                                               
              reason = ReadRespReason.END                                                        
              result = error, reason, opaque_data            
              return result                                                                                                               
                                                                                                           

Have a nice day

louis,

ChevalierLouis avatar Nov 24 '21 09:11 ChevalierLouis

Hi Louis, Glad to hear you are making progress.

These are the things that i might attack first:

  1. try to align your device_read with the demo server device_read. In particular, try setting error = vxi11.Error.NO_ERROR reason = vxi11.ReadRespReason.END If these give you problems then we can take it from there.
  2. Next, determine if the print(opaque_data) is giving you the results you expect. I think not as the for loop may not be appending to status. Perhaps you want states += str(status) inside the for loop? (dont forget to initialize states before the for...)
  3. Related, as i read the python docs for os.system() it is unclear to me what will be returned. If you are still having trouble you might write a small test program to explore os.system() without the added baggage of the vxi11 libraries etc to determine if that is in fact the command you want to be using.
  4. Finally, i see an inconsistency in the spelling of opaque. It most likely is not of consequence, but if its not a bug now, it will certainly become one ;-)

But after all that said, it sounds like this may be a new platform. Have you verified an unmodified version of the time-device.py runs properly on the new hardware?

c

coburnw avatar Nov 24 '21 22:11 coburnw

thank you I will correct the errors. Is it possible to do device_read(get: E1)? this will simplify the code

ChevalierLouis avatar Nov 25 '21 10:11 ChevalierLouis

Hello, you are indeed right os.system () only returns a 0 when the command is done. I need to learn how the gpiod lib works in python

ChevalierLouis avatar Nov 26 '21 08:11 ChevalierLouis