Package: picmd
picmdpicmd is a framework for creating applications that request and respond to AT commands using serial communication.Its main purpose is for use with Raspberry PI.Quick SampleCreate an instance ofPiCmdwith thecreatemethod and register the command handler with thehandlerdecorator.Start the application with therunmethod and wait for a command request.frompicmdimportPiCmdimporttimeapp=PiCmd.create('/dev/serial0')@app.handler(0x01)defgreeting_handler()->str:return'hello world'@app.handler(0x02)deffile_receive_handler(data:bytes):withopen('./tmp/received-%s.bin'%int(time.time()),'wb')asf:f.write(data)app.run()AT Command FormatCommand Request (Client -> Application)Hexadecimal data starting withAT*PIC=and ending withCRLF.The command type is specified by the first 8 bits.The command parameter size is represented by the second 16 bits. Then there is the content of the command parameters.The check parity is the XOR of the values from command type to command parameter.AT*PIC=\x01\x04\x00\x01\x00\x00\x00\x04\r\n
<-----><--><------><--------------><--><-->
   \     \      \     \               \  \_ command end delimiter (CRLF)
    \     \      \     \               \_ check parity
     \     \      \     \_ command data (The length changes depending on the value of "command data size")
      \     \      \_ command data size (max 0xffff)
       \     \_ command (max 0xff)
        \_ command start prefixCommand Response (Application -> Client)Hexadecimal data starting with*PIC:and ending withCRLF.The response status is specified by the first 8 bits.The response data size is represented by the second 16 bits. Then there is the content of the response datas.The check parity is the XOR of the values from response status to response data.OK*PIC:\x01\x04\x00\x01\x00\x00\x00\x04\r\nOK\r\n
<---><--><------><--------------><--><-------->
  \    \      \       \             \      \_ response end delimiter
   \    \      \       \             \_ check parity
    \    \      \       \_ response data (The length changes depending on the value of "response data size")
     \    \      \_ response data size (max 0xffff)
      \    \_ response status (0x01)
       \_ response start prefixERROR*PIC:\x07\x04\x00\x01\x00\x00\x00\x02\r\nERROR\r\n
<---><--><------><--------------><--><----------->
  \    \      \       \            \       \_ response end delimiter
   \    \      \       \            \_ check parity
    \    \      \       \_ response data (The length changes depending on the value of "response data size")
     \    \      \_ response data size (max 0xffff)
      \    \_ response status (values from 0x02 to 0xff)
       \_ response start prefixReserved value of response statusstatusdescription0x01No error0x02Invalid command format error0x03Invalid parity error0x04Command not found error0x05Invalid data length error0x06Command fail errorHow to confirm communicationSends the following command.AT\r\nIf the next message is received in the response, the communication confirmation is successful.\r\n
OK
\r\nCommand Handler InterfaceThe command handler function receives the byte data of the command parameter in the first argumentdataand the size of the command parameter in the second argumentsize. It is also possible to omit either or both of these.You can take a dependency set by theprovidefunction (see later) as an argument.Examples of handlers' argumentsAn example of a case where you want to receive both data and size.@app.handler(0x01)defhandler(data:bytes,size:int):....An example of receiving data only.@app.handler(0x01)defhandler(data:bytes):....Example of a case where both are not received.@app.handler(0x01)defhandler():....An example of receiving data and dependencies.@app.handler(0x01)defhandler(data:bytes,service1:Service1,service2:Service2):....When returning some kind of responseReturns a value of typebool,int,float,str, orbytes.@app.handler(0x01)defhandler(data:bytes,size:int)->Union[bool,int,float,str,bytes]:....returnresponse_dataWhen returning no responseReturns nothing.@app.handler(0x01)defhandler(data:bytes,size:int):....# nothing returnIf you want to return your domain error statusRaise an exception with thestatus_codeattribute.
If you want to return error message etc. as response data, adddescriptionattribute.classDomainException(Exception):status_code=0xffdescription='any error message'@app.handler(0x01)defhandler(data:bytes,size:int):....raiseDomainExceptionAPIPiCmdPiCmd.create(serial_port: str) -> PiCmdTake the serial port path as an argument and create an instance.@handler(command: int)Decorator that takes a command type as an argument and registers it as a handler.provide(provided: Dict[str, Any])Specifies the dependency to pass to the handler by dict.
The handler will receive the same arguments as the key name.for example.app.provide({'service1':service1,'service2':service2})import_handler_register(handler_register: HandlerRegister)Import the handlers registered in the HandlerRegister.run()Start accepting and responding to commands.HandlerRegisterIt is used to register handlers to be imported into PiCmd.@handler(command: int)Decorator that takes a command type as an argument and registers it as a handler.Client libraryThe libraries for the client are as follows.node-picmd(node.js)Change Log0.7.0Added HandlerRegister feature.0.6.1Fixed a response bug of the PING command.0.6.0Added a feature to confirm communication.0.5.0Added the feature to provide dependency.0.4.0Added support for omitting the arguments of the handler function.0.3.0Change the data format of the protocol.0.2.0Change request and resopnse prefix.0.1.0Initial release.LicenseMIT