def set_device_list(start_device: str, value_list: List[Union[int, float]], fx_datatype: FxDataType = FxDataType.Signed16 )-> None:
    rqst_bytes = bytearray(config.MONITOR_TIMER.to_bytes(2, 'little'))  # 監視タイマ(2byte)
    
    fx_dev = FxDevice(start_device)                                     # 先頭デバイスを文字列から扱いやすい形に変換
    rqst_bytes.extend(tools.Eth.get_command_bytes(                      # コマンドを示すデータバイト
        MCCommand.Write_List,
        extention= fx_dev.is_extended_device))
    rqst_bytes.extend(tools.Eth.get_device_bytes(fx_dev))               # 先頭デバイス番号+デバイスコードを示すバイト列

    word_length = fx_datatype.get_word_length() * len(value_list)       # デバイス点数(1byte)   ※本来ならばword数と言うべき
    rqst_bytes.extend(word_length.to_bytes(2, 'little'))                # (三菱の仕様から察するに,ここでの「デバイス」はint16の事)

    for val in value_list:                                              # 具体的な書き込みデータ ※注意!ここでは生成されるFxDevice のfx_devicetype とvalue だけが重要で、
        dev = FxDevice(start_device, fx_datatype, val)                  # デバイス名(特に番号)は割とどうでも良いために ループ内すべてstart_deviceを使っている。
        rqst_bytes.extend(dev.value_to_bytes())

    sd_data = tools.Eth.get_route_bytes()                               # アクセス経路まで
    sd_data.extend(len(rqst_bytes).to_bytes(2, 'little'))               # 要求データ長さ(2byte)
    sd_data.extend(rqst_bytes)                                          # 要求データ

    recievedData = tools.socket_send(sd_data)                           # ソケットで送信

    distinguished = tools.distinguish_reciedved_data(recievedData)      # データ判別
    ret_code = distinguished[0]
    return ret_code                                                     # set_device の場合は戻り値変換がないので,そのままの値を返しても良い。
def get_device_random(device_list: List[FxDevice]):
    rqst_bytes = bytearray(                         #
        config.MONITOR_TIMER.to_bytes(2, 'little')) # 監視タイマ(2byte)

    if config.CPU_SERIES == CPUSeries.iQ_R:         # Random 読みはbit 版がないらしい
        rqst_bytes.extend([0x03,0x04,0x02,0x00])    # ワード,iQ-R   モニタ条件を指定 は無視 20.03.16
    else:
        rqst_bytes.extend([0x03,0x04,0x00,0x00])    # ワード,Q/L
    
    # single word とdouble word を分ける    ※良いgroupbyが見つからなかった
    single_list: List[FxDevice] =[]
    double_list: List[FxDevice] =[]
    for dev in device_list:
        if dev.fxdatatype.get_word_length() == 1: single_list.append(dev)
        elif dev.fxdatatype.get_word_length() == 2: double_list.append(dev)

    rqst_bytes.extend(len(single_list).to_bytes(1, 'little'))   # single wordデータ長さ(1byte)
    rqst_bytes.extend(len(double_list).to_bytes(1, 'little'))   # double wordデータ長さ(1byte)

    for dev in single_list:
        rqst_bytes.extend(tools.Eth.get_device_bytes(dev))    # デバイス名+デバイスコード:single word
        pass

    for dev in double_list:
        rqst_bytes.extend(tools.Eth.get_device_bytes(dev))    # デバイス名+デバイスコードdouble word
        pass

    sd_data = tools.Eth.get_route_bytes()            # アクセス経路まで
    sd_data.extend(len(rqst_bytes).to_bytes(2, 'little'))   # 要求データ長さ(2byte)
    sd_data.extend(rqst_bytes)                              # 要求データ

    recievedData = tools.socket_send(sd_data)    # ソケットで送信

    if recievedData == None:                                # 通信失敗
        return None
    
    distinguished = tools.distinguish_reciedved_data(recievedData)   # データ判別

    ret_code = distinguished[0]
    if not ret_code ==0: return ret_code

    count = 0                                               # デバイスリストに値を格納していく
    data_bytes = distinguished[1]

    for dev in single_list:
        byte_length = dev.fxdatatype.get_word_length() * 2
        dev.set_value_from_bytes(data_bytes[count:count+byte_length])
        count += byte_length

    for dev in double_list:
        byte_length = dev.fxdatatype.get_word_length() * 2
        dev.set_value_from_bytes(data_bytes[count:count+byte_length])
        count += byte_length

    return 0
def set_device_random(device_list: List[FxDevice]):
    rqst_bytes = bytearray(                         #
        config.MONITOR_TIMER.to_bytes(2, 'little')) # 監視タイマ(2byte)
        
    rqst_bytes.extend(tools.Eth.get_command_bytes(MCCommand.Write_Random))  # コマンドを示すデータバイト
        
    # single word とdouble word を分ける    ※良いgroupbyが見つからなかった
    single_list:List[FxDevice] =[]
    double_list:List[FxDevice] =[]
    for dev in device_list:
        if dev.fxdatatype.get_word_length() == 1: single_list.append(dev)
        elif dev.fxdatatype.get_word_length() == 2: double_list.append(dev)

    rqst_bytes.extend(len(single_list).to_bytes(1, 'little'))   # singleデータ長さ(1byte)
    rqst_bytes.extend(len(double_list).to_bytes(1, 'little'))   # doubleデータ長さ(1byte)

    for dev in single_list:
        rqst_bytes.extend(tools.Eth.get_device_bytes(dev))    # デバイス名+デバイスコード
        rqst_bytes.extend(dev.value_to_bytes())
        pass

    for dev in double_list:
        rqst_bytes.extend(tools.Eth.get_device_bytes(dev))
        rqst_bytes.extend(dev.value_to_bytes())
        pass

    sd_data = tools.Eth.get_route_bytes()            # アクセス経路まで
    sd_data.extend(len(rqst_bytes).to_bytes(2, 'little'))   # 要求データ長さ(2byte)
    sd_data.extend(rqst_bytes)                              # 要求データ

    recievedData = tools.socket_send(sd_data)    # ソケットで送信

    if recievedData == None:                                # 通信失敗
        return None
    
    distinguished = tools.distinguish_reciedved_data(recievedData)   # データ判別
    ret_code = distinguished[0]
    return ret_code
def get_device_list(start_device: str, device_count: int, fx_datatype: FxDataType = FxDataType.Signed16 )-> Union[None,int, List[Union[int,float]]]:    # MCProtocol的にはこっちがメインメソッドらしい
    rqst_bytes = bytearray(config.MONITOR_TIMER.to_bytes(2, 'little'))  # 監視タイマ(2byte)
    fx_dev = FxDevice(start_device)                                     # 先頭デバイスを文字列から扱いやすい形に変換

    rqst_bytes.extend(tools.Eth.get_command_bytes(              # コマンドを示すデータバイト
        MCCommand.Read_List,
        extention= fx_dev.is_extended_device))
    rqst_bytes.extend(tools.Eth.get_device_bytes(fx_dev))       # 開始デバイスを示すバイト列


    word_length = fx_datatype.get_word_length() * device_count  # デバイス点数(2byte) 
    rqst_bytes.extend(word_length.to_bytes(2, 'little'))        # 三菱の仕様から察するに,ここでの「デバイス」はint16の事 本来ならばword数と言うべき。

    sd_data = tools.Eth.get_route_bytes()                       # アクセス経路まで
    sd_data.extend(len(rqst_bytes).to_bytes(2, 'little'))       # 要求データ長さ(2byte)
    sd_data.extend(rqst_bytes)                                  # 要求データ

    recievedData = tools.socket_send(sd_data)                   # ソケットで送信

    if recievedData == None: return None                        # 通信失敗
            
    distinguished = tools.distinguish_reciedved_data(recievedData)   # データ判別
    ret_code = distinguished[0]

    if not ret_code ==0: return ret_code                        # エラーコードだった場合は処理を中止

    count = 0                                                   # デバイスリストに値を格納していく
    data_bytes = distinguished[1]
    value_list = []

    for c in range(device_count):                               # ※ここではループ変数 c は使わない。→もっといい方法ないか?
        dev = FxDevice(start_device, fx_datatype)               # デバイス名(特に番号)は割とどうでも良いために ループ内すべてstart_deviceを使っている。
        byte_length = fx_datatype.get_word_length() * 2         # バイト数
        dev.set_value_from_bytes(data_bytes[count:count+byte_length])   # bytes から値を代入
        value_list.append(dev.value)
        count += byte_length

    return value_list