Esempio n. 1
0
def parse_request(request):
    interface = request.get('bus')
    if interface == None:
        interface = CAN_SEND_INTERFACE
    else:
        interface = interface[0]
    try:
        bus = CAN.Bus(interface)
    except OSError:
        raise BadRequest("bus '" + interface + "' does not exist")
    id = request.get('id')
    if id == None:
      raise BadRequest("id not specified")
    id = int(id[0])
    data = request.get('data[]') # POST
    if data == None:
        data = request.get('data') # GET
        if data == None:
            data = [] # parse_url removes data field if empty array
        else:
            data = data[0].strip('[]').split(',')
    if len(data) == 1:
      if data[0] == '':
        data = []
    data = list(map(int, data))
    msg = CAN.Message(id, data)
    return (bus, msg)
Esempio n. 2
0
 def _send_sync(self):
     sync_object = self.od.get(ODI_SYNC)
     if sync_object is not None:
         sync_value = sync_object.get(ODSI_VALUE)
         if sync_value is not None:
             sync_id = sync_value & 0x3FF
             msg = CAN.Message(sync_id)
             self._send(msg)
Esempio n. 3
0
 def _heartbeat_consumer_timeout(self, id):
     if self.nmt_state != NMT_STATE_STOPPED:
         emcy_id = self.od.get(ODI_EMCY_ID)
         if emcy_id is not None:
             msg = CAN.Message(
                 emcy_id,
                 (EMCY_HEARTBEAT_BY_NODE + id).to_bytes(2, byteorder='big')
                 + self.od.get(ODI_ERROR).get(ODSI_VALUE).to_bytes(
                     1, byteorder='big') + b'\x00\x00\x00\x00\x00')
             self._send(msg)
Esempio n. 4
0
def heartbeat_consumer_timeout(id):
    global active_bus, canopen_od, nmt_state, node_id
    if nmt_state != CANopen.NMT_STATE_STOPPED:
        msg = CAN.Message(
            canopen_od.get(CANopen.ODI_EMCY_ID),
            (CANopen.EMCY_HEARTBEAT_BY_NODE + id).to_bytes(
                2, byteorder='big') + canopen_od.get(CANopen.ODI_ERROR).get(
                    CANopen.ODSI_VALUE).to_bytes(1, byteorder='big') +
            b'\x00\x00\x00\x00\x00')
        active_bus.send(msg)
Esempio n. 5
0
 def _send_pdo(self, i):
     i = i - 1
     data = bytes()
     tpdo_mp = self.od.get(ODI_TPDO1_MAPPING_PARAMETER + i)
     if tpdo_mp is not None:
         for j in range(tpdo_mp.get(ODSI_VALUE, 0)):
             mapping_param = tpdo_mp.get(j + 1)
             if mapping_param is not None:
                 mapping_object = self.od.get(mapping_param >> 16)
                 if mapping_object is not None:
                     mapping_value = mapping_object.get((mapping_param >> 8)
                                                        & 0xFF)
                     if mapping_value is not None:
                         data = data + mapping_value.to_bytes(
                             (mapping_param & 0xFF) // 8, byteorder='big')
         msg = CAN.Message(((FUNCTION_CODE_TPDO1 +
                             (2 * i)) << FUNCTION_CODE_BITNUM) + self.id,
                           data)
         self._send(msg)
Esempio n. 6
0
 def recv(self, msg: CAN.Message):
     id = msg.arbitration_id
     data = msg.data
     rtr = msg.is_remote_frame
     fc = (id >> FUNCTION_CODE_BITNUM) & 0xF
     if rtr:
         target_node = id & 0x7F
         if target_node == self.id or target_node == BROADCAST_NODE_ID:
             if self.nmt_state == NMT_STATE_OPERATIONAL:
                 if fc == FUNCTION_CODE_TPDO1:
                     tpdo1_cp = self.od.get(
                         ODI_TPDO1_COMMUNICATION_PARAMETER)
                     if tpdo1_cp is not None:
                         tpdo1_cp_id = tpdo1_cp.get(ODSI_TPDO_COMM_PARAM_ID)
                         if tpdo1_cp_id is not None and (
                                 tpdo1_cp_id >>
                                 TPDO_COMM_PARAM_ID_VALID_BITNUM
                         ) & 1 == 0 and (
                                 tpdo1_cp_id >>
                                 TPDO_COMM_PARAM_ID_RTR_BITNUM) & 1 == 0:
                             self._send_pdo(1)
             elif fc == FUNCTION_CODE_NMT_ERROR_CONTROL:
                 self._send_heartbeat()
     elif fc == FUNCTION_CODE_NMT:
         command = id & 0x7F
         if command == NMT_NODE_CONTROL:
             target_node = data[1]
             if target_node == self.id or target_node == BROADCAST_NODE_ID:
                 cs = data[0]
                 if cs == NMT_NODE_CONTROL_START:
                     self.nmt_state = NMT_STATE_OPERATIONAL
                 elif cs == NMT_NODE_CONTROL_STOP:
                     self.nmt_state = NMT_STATE_STOPPED
                 elif cs == NMT_NODE_CONTROL_PREOPERATIONAL:
                     self.nmt_state = NMT_STATE_PREOPERATIONAL
                 elif cs == NMT_NODE_CONTROL_RESET_NODE:
                     self.reset()
                 elif cs == NMT_NODE_CONTROL_RESET_COMMUNICATION:
                     self.reset_communication()
     elif fc == FUNCTION_CODE_SYNC and self.nmt_state == NMT_STATE_OPERATIONAL:
         for i in range(4):
             tpdo_cp = self.od.get(ODI_TPDO1_COMMUNICATION_PARAMETER + i)
             if tpdo_cp is not None:
                 tpdo_cp_id = tpdo_cp.get(ODSI_TPDO_COMM_PARAM_ID)
                 if tpdo_cp_id is not None and (
                         tpdo_cp_id >>
                         TPDO_COMM_PARAM_ID_VALID_BITNUM) & 1 == 0:
                     tpdo_cp_type = tpdo_cp.get(ODSI_TPDO_COMM_PARAM_TYPE)
                     if tpdo_cp_type is not None and (
                         (tpdo_cp_type >= 0 and tpdo_cp_type <= 240)
                             or tpdo_cp_type == 252):
                         self._send_pdo(i + 1)
     elif fc == FUNCTION_CODE_SDO_RX and self.nmt_state != NMT_STATE_STOPPED:
         sdo_server_object = self.od.get(ODI_SDO_SERVER)
         if sdo_server_object is not None:
             sdo_server_id = sdo_server_object.get(ODSI_SERVER_DEFAULT_CSID)
             if sdo_server_id is not None and id == sdo_server_id:
                 ccs = (data[0] >> SDO_CCS_BITNUM) & (2**SDO_CCS_LENGTH - 1)
                 if len(data) >= 4:
                     odi = (data[1] << 8) + data[2]
                     odsi = data[3]
                     if odi in self.od:
                         obj = self.od.get(odi)
                         if odsi in obj:
                             if ccs == SDO_CCS_UPLOAD:
                                 scs = SDO_SCS_UPLOAD
                                 sdo_data = obj.get(odsi)
                             elif ccs == SDO_CCS_DOWNLOAD:
                                 scs = SDO_SCS_DOWNLOAD
                                 n = (data[0] >> SDO_N_BITNUM) & (
                                     2**SDO_N_LENGTH - 1)
                                 self.od.update(
                                     {
                                         odi:
                                         int.from_bytes(data[4:],
                                                        byteorder='big')
                                     }
                                 )  # Could be data[4:7-n], or different based on data type
                                 sdo_data = 0
                             else:
                                 scs = SDO_CS_ABORT
                                 sdo_data = SDO_ABORT_INVALID_CS
                         else:
                             scs = SDO_CS_ABORT
                             sdo_data = SDO_ABORT_SUBINDEX_DNE
                     else:
                         scs = SDO_CS_ABORT
                         sdo_data = SDO_ABORT_OBJECT_DNE
                 else:
                     odi = 0x0000
                     odsi = 0x00
                     scs = SDO_CS_ABORT
                     sdo_data = SDO_ABORT_GENERAL  # Don't see one specifically for sending not enough data bytes in the CAN msg (malformed SDO msg)
                 sdo_data = sdo_data.to_bytes(4, byteorder='big')
                 n = 4 - len(sdo_data)
                 data = [(scs << SDO_SCS_BITNUM) + (n << SDO_N_BITNUM) +
                         (1 << SDO_E_BITNUM) + (1 << SDO_S_BITNUM),
                         (odi >> 8), (odi & 0xFF), (odsi)] + list(sdo_data)
                 msg = CAN.Message(sdo_server_id, data)
                 self._send(msg)
             elif fc == FUNCTION_CODE_NMT_ERROR_CONTROL:
                 producer_id = id & 0x7F
                 if producer_id in self._heartbeat_consumer_timers:
                     self._heartbeat_consumer_timers.get(
                         producer_id).cancel()
                 heartbeat_consumer_time_object = self.od.get(
                     ODI_HEARTBEAT_CONSUMER_TIME)
                 if heartbeat_consumer_time_object is not None:
                     heartbeat_consumer_time = heartbeat_consumer_time_object.get(
                         ODSI_HEARTBEAT_CONSUMER_TIME, 0) / 1000
                 else:
                     heartbeat_consumer_time = 0
                 if heartbeat_consumer_time != 0:
                     heartbeat_consumer_timer = Timer(
                         heartbeat_consumer_time,
                         self._heartbeat_consumer_timeout, [producer_id])
                     heartbeat_consumer_timer.start()
                     self._heartbeat_consumer_timers.update(
                         {producer_id: heartbeat_consumer_timer})
Esempio n. 7
0
 def _send_heartbeat(self):
     msg = CAN.Message(
         (FUNCTION_CODE_NMT_ERROR_CONTROL << FUNCTION_CODE_BITNUM) +
         self.id, [self.nmt_state])
     self._send(msg)
Esempio n. 8
0
 def _send_bootup(self):
     msg = CAN.Message((
         FUNCTION_CODE_NMT_ERROR_CONTROL << FUNCTION_CODE_BITNUM) + self.id)
     self._send(msg)
Esempio n. 9
0
def send_heartbeat():
    global active_bus, node_id, nmt_state
    msg = CAN.Message((CANopen.FUNCTION_CODE_NMT_ERROR_CONTROL <<
                       CANopen.FUNCTION_CODE_BITNUM) + node_id, [nmt_state])
    active_bus.send(msg)
Esempio n. 10
0
def send_bootup():
    global active_bus, node_id
    msg = CAN.Message((CANopen.FUNCTION_CODE_NMT_ERROR_CONTROL <<
                       CANopen.FUNCTION_CODE_BITNUM) + node_id)
    active_bus.sendall(msg)
Esempio n. 11
0
def send_sync():
    global active_bus, canopen_od
    sync_id = canopen_od.get(CANopen.ODI_SYNC).get(CANopen.ODSI_VALUE) & 0x3FF
    msg = CAN.Message(sync_id)
    active_bus.send(msg)
Esempio n. 12
0
         ) & 1 == 1:
             data = bytes()
             for i in range(
                     canopen_od.get(
                         CANopen.ODI_TPDO1_MAPPING_PARAMETER
                     ).get(CANopen.ODSI_VALUE)):
                 mapping = canopen_od.get(
                     CANopen.ODI_TPDO1_MAPPING_PARAMETER
                 ).get(i + 1)
                 data = data + canopen_od.get(
                     mapping >> 16).get(
                         (mapping >> 8) & 0xFF).to_bytes(
                             (mapping & 0xFF) // 8,
                             byteorder='big')
             msg = CAN.Message(
                 (CANopen.FUNCTION_CODE_TPDO1 <<
                  CANopen.FUNCTION_CODE_BITNUM) + node_id,
                 data)
             active_bus.send(msg)
         elif fc == CANopen.FUNCTION_CODE_NMT_ERROR_CONTROL:
             data = [nmt_state]
             msg = CAN.Message(
                 (CANopen.FUNCTION_CODE_NMT_ERROR_CONTROL <<
                  CANopen.FUNCTION_CODE_BITNUM) + node_id,
                 data)
             active_bus.send(msg)
 elif fc == CANopen.FUNCTION_CODE_NMT:
     command = id & 0x7F
     if command == CANopen.NMT_NODE_CONTROL:
         target_node = data[1]
         if target_node == node_id or target_node == CANopen.BROADCAST_NODE_ID:
             cs = data[0]