Ejemplo n.º 1
0
def sim_hop():
    ber = 0.0001
    chunk_size = 50
    per = 1 - (1 - ber)**(chunk_size * 8)
    loop_num = 5
    hop = range(1, 6)
    w1_size = 0.4
    p1 = 0.4
    for h in tqdm(hop):
        fountain = EW_Fountain(m,
                               chunk_size=chunk_size,
                               w1_size=w1_size,
                               w1_pro=p1)
        for j in tqdm(range(loop_num)):
            drop_id = 0
            w1_done_t = 0
            glass = Glass(Fountain.num_chunks)
            while not glass.isDone():
                a_drop = fountain.droplet()
                ew_drop = EW_Droplet(a_drop.data,
                                     a_drop.seed,
                                     a_drop.num_chunks,
                                     w1_size,
                                     w1_pro=p1)
                glass.addDroplet(ew_drop)
                if glass.is_w1_done() and w1_done_t == 0:
                    w1_done_t = drop_id
                del a_drop
                del ew_drop
Ejemplo n.º 2
0
class Receiver:
    def __init__(
        self,
        bus,
        device,
        port,
        baudrate,
        timeout,
    ):
        self.spiRecv = spidev.SpiDev()
        self.spiRecv.open(bus, device)
        self.spiRecv.max_speed_hz = 6250000  #976000
        self.spiRecv.mode = 0b00

        self.spiSend = spidev.SpiDev()
        self.spiSend.open(bus, 0)
        self.spiSend.max_speed_hz = 6250000  #976000
        self.spiSend.mode = 0b00

        # 串口和spi初始化
        spi_init()
        self.port = serial.Serial(port, baudrate)

        self.packet_id = 0  # 数据包数量
        self.drop_id = 0  # 校验正确的有效数据包数量
        self.real_drop_id = 0  # dropid除去度函数切换和进度包更新时收到的drop
        self.glass = Glass(0)
        self.chunk_size = 0
        self.recv_done_flag = False
        self.feedback_ack_flag = False  # 用于度函数切换过程不接收
        self.feedback_send_done = False
        self.chunk_process = []
        self.feedback_idx = 0
        self.data_rec = ""
        self.recv_dir = os.path.join(
            RECV_PATH,
            time.asctime().replace(' ', '_').replace(':', '_'))

        # 吞吐量统计
        self.packid_save = []
        self.dropid_save = []
        self.valid_dropid_save = []
        self.packs_per_sec = []
        self.drops_per_sec = []
        self.valid_drops_per_sec = []
        self.ttl_timer_start = False
        self.t0 = 0
        self.t1 = 0

        self.process_bytes = b''
        self.decode_time = []  # 用于统计每个编码包的译码时间

    '''LT喷泉码接收解码部分'''

    def begin_to_catch(self):
        a_drop_bytes = self.catch_a_drop_spi()  # bytes

        if a_drop_bytes is not None:
            decode_t0 = time.time()
            # 从收到第一个包之后,开启定时记录吞吐量线程,记录时间
            if self.ttl_timer_start == False:
                self.t0 = time.time()
                self.creat_ttl_Timer()
                self.ttl_timer_start = True

            self.packet_id += 1
            print("Recv Packet id : ", self.packet_id)
            if len(a_drop_bytes) > 0:
                check_data = recv_check(a_drop_bytes)  # 接收校验

                if not check_data == None:
                    self.drop_byte_size = len(check_data)
                    self.add_a_drop(check_data)  # bytes --- drop --- bits
                    decode_t1 = time.time()
                    self.decode_time.append(decode_t1 - decode_t0)

    def catch_a_drop_spi(self):
        if GPIO.input(25):
            spi_recv = self.spiRecv.readbytes(239)
            rec_bytes = bytes(spi_recv)
            frame_len = len(rec_bytes)
            print("framelen: ", frame_len)

            # 去掉末尾补充的0
            if (frame_len > 1):
                while (rec_bytes[frame_len - 1] == 0 and frame_len >= 1):
                    frame_len = frame_len - 1
            rec_bytes = rec_bytes[:frame_len]
            print("droplen: ", frame_len)

            self.data_rec = rec_bytes
            # 判断帧头帧尾
            if self.data_rec[0:2] == b'##' and self.data_rec[
                    frame_len - 2:frame_len] == b'$$':
                data_array = bytearray(self.data_rec)
                data_array.pop(0)
                data_array.pop(0)
                data_array.pop()
                data_array.pop()
                return bytes(data_array)
            else:
                print(self.data_rec)
                print('Wrong receive frame !')

    def add_a_drop(self, d_byte):
        self.drop_id += 1
        print("====================")
        print("Recv dropid : ", self.drop_id)
        print("====================")

        print('glass_process_history len: ',
              len(self.glass.glass_process_history))
        drop = self.glass.droplet_from_Bytes(d_byte)  # drop
        if self.glass.num_chunks == 0:
            print('init num_chunks : ', drop.num_chunks)
            self.glass = Glass(drop.num_chunks)  # 初始化接收glass
            self.chunk_size = len(drop.data)

        #若为ew,则需要将drop转为ewdrop,两个drop里译码方式不一样
        ew_drop = EW_Droplet(drop.data, drop.seed, drop.num_chunks,
                             drop.process, drop.func_id, drop.feedback_idx)
        print('drop data len: ', len(drop.data))

        self.glass.addDroplet(ew_drop)

        # 这里解决度函数切换过程不接收,解决进度包更新过程不接收
        # if (self.feedback_ack_flag==False) or (self.feedback_ack_flag==True and ew_drop.func_id==1 and ew_drop.feedback_idx==self.feedback_idx-1):
        #     self.real_drop_id += 1
        #     self.glass.addDroplet(ew_drop)         # glass add drops
        #     print("=============================================================")
        #     print("除去度函数切换和进度包更新时收到的drop,Real_Recv_dropid : ", self.real_drop_id)
        #     print("=============================================================")
        #     self.feedback_send_done=False

        logging.info('=============================')
        logging.info('Decode Progress: ' + str(self.glass.chunksDone()) + '/' +
                     str(self.glass.num_chunks))
        logging.info('=============================')

        # 接收完成
        if self.glass.isDone():
            self.recv_done_flag = True
            self.t1 = time.time()
            logging.info('============Recv done===========')
            logging.info("Fountain time elapsed:" + str(self.t1 - self.t0))
            # 接收完成写入图像
            img_data = self.glass.get_bits()
            os.mkdir(self.recv_dir)
            with open(os.path.join(self.recv_dir, "img_recv" + ".bmp"),
                      'wb') as f:
                f.write(img_data)

            # 串口模拟水声延迟进行反馈
            t1 = threading.Timer(1.8, self.send_recv_done_ack)
            t1.start()

            # 实际写入水声通信机进行反馈
            # self.send_recv_done_ack() # 接收完成返回ack

            # 记录吞吐量
            self.cal_ttl()
            print('packet_id history: ', self.packid_save,
                  len(self.packid_save))
            print('packets_per_sec: ', self.packs_per_sec,
                  len(self.packs_per_sec))
            print('drop_id history: ', self.dropid_save, len(self.dropid_save))
            logging.info('Send Sonic Fountain ACK done')
            logging.info('Recv Packets: : ' + str(self.packet_id))
            logging.info('Recv drops: ' + str(self.drop_id))
            logging.info('Feedback num: ' + str(self.feedback_idx))

            print('drops_per_sec: ', self.drops_per_sec,
                  len(self.drops_per_sec))
            res = pd.DataFrame({
                'packet_id_history': self.packid_save,
                'packets_per_sec': self.packs_per_sec,
                'drop_id_history': self.dropid_save,
                'drops_per_sec': self.drops_per_sec
            })
            res.to_csv(
                ('data_save/Recv_ttl' + '_' +
                 time.asctime().replace(' ', '_').replace(':', '_') + '.csv'),
                mode='a')

            # print('avgs_decode_time: ', float(sum(self.decode_time)/len(self.decode_time)))
            # print('max_decode_time:', max(self.decode_time))
            # print('min_decode_time:', min(self.decode_time))

        # 反馈
        n1 = self.glass.w1_done_dropid
        n2 = 30
        if self.glass.is_w1_done(0.6) and self.recv_done_flag == False:
            if (self.drop_id - n1) % n2 == 0:
                process = self.glass.getProcess()
                # 用于添加反馈历史数据, 用于droplet参数,正确译码
                self.chunk_process = process[0]
                self.glass.glass_process_history.append(self.chunk_process)
                # 用于实际反馈
                process_bitmap = process[1]
                # self.process_bytes = self.bit2hex(process_bitmap) # 实际水声通信机反馈可能需要用到这个
                # print(process_bitmap)
                # print(self.process_bytes)
                process_bits = bitarray.bitarray(process_bitmap)
                self.process_bytes = process_bits.tobytes()

                # 串口模拟水声延迟进行反馈
                t = threading.Timer(1.8, self.send_feedback)
                t.start()

                # 实际写入水声通信机进行反馈
                # self.send_feedback()
                print("Feedback chunks: ", self.chunk_process)
                print("Feedback chunks num: ", len(self.chunk_process))
                print("Feedback idx: ", self.feedback_idx)
                self.feedback_idx += 1
                self.feedback_ack_flag = True
                self.feedback_send_done = True

    # 定时器线程每隔1s记录发包数,即吞吐量
    def save_throughout_put(self):
        if (self.recv_done_flag == False):
            self.packid_save.append(self.packet_id)
            self.dropid_save.append(self.drop_id)
            self.valid_dropid_save.append(self.real_drop_id)
            self.creat_ttl_Timer()

    def creat_ttl_Timer(self):
        if (self.recv_done_flag == False):
            t = threading.Timer(1, self.save_throughout_put)
            t.start()

    # 计算吞吐量
    def cal_ttl(self):
        idx = 0
        while idx < len(self.packid_save):
            if idx == 0:
                self.packs_per_sec.append(self.packid_save[0])
            else:
                self.packs_per_sec.append(self.packid_save[idx] -
                                          self.packid_save[idx - 1])
            idx += 1
        idx = 0
        while idx < len(self.dropid_save):
            if idx == 0:
                self.drops_per_sec.append(self.dropid_save[0])
            else:
                self.drops_per_sec.append(self.dropid_save[idx] -
                                          self.dropid_save[idx - 1])
            idx += 1

    # 串口发送译码完成ack
    def send_recv_done_ack(self):
        if self.recv_done_flag:
            # M = b'M\r\n'
            # self.port.write(M)
            # self.port.flushOutput()
            # time.sleep(0.01)

            ack = b'#$\r\n'
            acksend = bytearray(ack)
            self.port.write(acksend)
            self.port.flushOutput()

    # 串口反馈译码进度
    def send_feedback(self):
        fb = b'$#' + self.process_bytes + b'\r\n'
        # M = b'M\r\n'
        # self.port.write(M)
        # self.port.flushOutput()
        # time.sleep(0.01)
        self.port.write(fb)
        self.port.flushOutput()

    def bit2hex(self, bit_array_source):
        bit_array = bit_array_source
        a = len(bit_array) % 4
        for j in range(0, a):
            bit_array.append(0)
        result = b''
        i = 0
        while i < len(bit_array):
            bit4 = bit_array[i:i + 4]
            if (bit4 == [0, 0, 0, 0]):
                result += b'0'
            elif (bit4 == [0, 0, 0, 1]):
                result += b'1'
            elif (bit4 == [0, 0, 1, 0]):
                result += b'2'
            elif (bit4 == [0, 0, 1, 1]):
                result += b'3'
            elif (bit4 == [0, 1, 0, 0]):
                result += b'4'
            elif (bit4 == [0, 1, 0, 1]):
                result += b'5'
            elif (bit4 == [0, 1, 1, 0]):
                result += b'6'
            elif (bit4 == [0, 1, 1, 1]):
                result += b'7'
            elif (bit4 == [1, 0, 0, 0]):
                result += b'8'
            elif (bit4 == [1, 0, 0, 1]):
                result += b'9'
            elif (bit4 == [1, 0, 1, 0]):
                result += b'a'
            elif (bit4 == [1, 0, 1, 1]):
                result += b'b'
            elif (bit4 == [1, 1, 0, 0]):
                result += b'c'
            elif (bit4 == [1, 1, 0, 1]):
                result += b'd'
            elif (bit4 == [1, 1, 1, 0]):
                result += b'e'
            elif (bit4 == [1, 1, 1, 1]):
                result += b'f'
            i += 4
        return result
class NodeRLY:
    def __init__(self, portSNC, baudrateSNC, timeoutSNC, portROV, baudrateROV,
                 timeoutROV):
        self.ID = 1  #本节点id
        self.routing_table = [0, 1, 2]  #路由
        self.snc_handshake_done = False
        self.vlc_handshake_done = False
        self.vlc_handshake_timedout = False

        # 初始化spi发送
        self.spiSend = spidev.SpiDev()
        self.spiSend.open(0, 0)  # bus device
        self.spiSend.max_speed_hz = 6250000  #976000
        self.spiSend.mode = 0b00

        # 初始化spi接收
        self.spiRecv = spidev.SpiDev()
        self.spiRecv.open(0, 1)
        self.spiRecv.max_speed_hz = 6250000  #976000
        self.spiRecv.mode = 0b00

        # 初始化光通信spi、水声串口、ROV串口
        spi_init()
        self.acoustic = Acoustic(portSNC, baudrateSNC, timeoutSNC)
        self.rov = ROV(portROV, baudrateROV, timeoutROV)

        # 自动对准
        self.align_rov_state = 0  #记录上次循环的转向状态,0为左,1为右

        # 喷泉码接收
        self.rx_packet_id = 0
        self.rx_drop_id = 0
        self.glass = Glass(0)
        self.chunk_size = 0
        self.recv_done_flag = False
        self.feedback_ack_flag = False  # 用于度函数切换过程不接收
        self.chunk_process = []
        self.feedback_idx = 0
        self.data_rec = ""
        self.recv_dir = os.path.join(
            RECV_PATH,
            time.asctime().replace(' ', '_').replace(':', '_'))

        self.rx_packid_save = []
        self.rx_dropid_save = []
        self.rx_packs_per_sec = []
        self.rx_drops_per_sec = []
        self.rx_ttl_timer_start = False
        self.t0 = 0
        self.t1 = 0
        self.process_bytes = b''
        self.img_recv_bits = bitarray.bitarray(endian='big')
        self.decode_time = []

        # 喷泉码中继发送
        self.tx_drop_id = 0
        self.recvdone_ack = False
        self.chunk_process = []
        self.feedback_num = 0
        self.tx_dropid_save = []

    '''LT喷泉码接收解码部分'''

    def begin_to_catch(self):
        a_drop_bytes = self.catch_a_drop_spi()  # bytes

        if a_drop_bytes is not b'':
            decode_t0 = time.time()
            # 从收到第一个包之后,开启定时记录吞吐量线程,记录时间
            if self.rx_ttl_timer_start == False:
                self.t0 = time.time()
                self.creat_ttl_Timer()
                self.rx_ttl_timer_start = True

            self.rx_packet_id += 1
            print("Recv Packet id : ", self.rx_packet_id)
            if len(a_drop_bytes) > 0:
                check_data = recv_check(a_drop_bytes)
                if not check_data == b'':
                    self.add_a_drop(check_data)  # bytes --- drop --- bits

    def catch_a_drop_spi(self):
        if GPIO.input(25):
            spi_recv = self.spiRecv.readbytes(239)
            rec_bytes = bytes(spi_recv)
            frame_len = len(rec_bytes)
            print("framelen: ", frame_len)

            if (frame_len > 1):
                while (rec_bytes[frame_len - 1] == 0 and frame_len >= 1):
                    frame_len = frame_len - 1
            rec_bytes = rec_bytes[:frame_len]
            print("droplen: ", frame_len)

            self.data_rec = rec_bytes
            if self.data_rec[0:2] == b'##' and self.data_rec[
                    frame_len - 2:frame_len] == b'$$':
                data_array = bytearray(self.data_rec)
                data_array.pop(0)
                data_array.pop(0)
                data_array.pop()
                data_array.pop()
                return bytes(data_array)
            else:
                print(self.data_rec)
                print('Wrong receive frame !')
                return b''
        else:
            return b''

    def add_a_drop(self, d_byte):
        self.rx_drop_id += 1
        print("====================")
        print("Recv dropid : ", self.rx_drop_id)
        print("====================")

        print('glass_process_history len: ',
              len(self.glass.glass_process_history))
        drop = self.glass.droplet_from_Bytes(d_byte)  # drop
        if self.glass.num_chunks == 0:
            print('init num_chunks : ', drop.num_chunks)
            self.glass = Glass(drop.num_chunks)  # 初始化接收glass
            self.chunk_size = len(drop.data)

        #若为ew,则需要将drop转为ewdrop,两个drop里译码方式不一样
        ew_drop = EW_Droplet(drop.data, drop.seed, drop.num_chunks,
                             drop.process, drop.func_id, drop.feedback_idx)
        print('drop data len: ', len(drop.data))

        self.glass.addDroplet(ew_drop)

        logging.info('=============================')
        logging.info('Decode Progress: ' + str(self.glass.chunksDone()) + '/' +
                     str(self.glass.num_chunks))
        logging.info('=============================')

        # 接收完成
        if self.glass.isDone():
            self.recv_done_flag = True
            self.t1 = time.time()
            logging.info('============Recv done===========')
            logging.info("Fountain time elapsed:" + str(self.t1 - self.t0))
            # 接收完成写入图像
            img_data = self.glass.get_bits()
            self.img_recv_bits = img_data
            os.mkdir(self.recv_dir)
            with open(os.path.join(self.recv_dir, "img_recv" + ".bmp"),
                      'wb') as f:
                f.write(img_data)

            self.send_recv_done_ack()  # 接收完成返回ack

            # 记录吞吐量
            self.rx_cal_ttl()
            logging.info('Recv drops: ' + str(self.rx_drop_id))
            logging.info('Feedback num: ' + str(self.feedback_idx))

            print('drops_per_sec: ', self.rx_drops_per_sec,
                  len(self.rx_drops_per_sec))
            res = pd.DataFrame({
                'packet_id_history': self.rx_packid_save,
                'packets_per_sec': self.rx_packs_per_sec,
                'drop_id_history': self.rx_dropid_save,
                'drops_per_sec': self.rx_drops_per_sec
            })
            res.to_csv(
                ('data_save/Recv_ttl' + '_' +
                 time.asctime().replace(' ', '_').replace(':', '_') + '.csv'),
                mode='a')

        # 反馈
        n1 = self.glass.w1_done_dropid
        n2 = 30
        if self.glass.is_w1_done(0.6) and self.recv_done_flag == False:
            if (self.rx_drop_id - n1) % n2 == 0:
                process = self.glass.getProcess()
                # 用于添加反馈历史数据, 用于droplet参数,正确译码
                self.chunk_process = process[0]
                self.glass.glass_process_history.append(self.chunk_process)
                # 用于实际反馈
                process_bitmap = process[1]
                # self.process_bytes = self.bit2hex(process_bitmap)
                # print(process_bitmap)
                # print(self.process_bytes)
                process_bits = bitarray.bitarray(process_bitmap)
                self.process_bytes = process_bits.tobytes()

                self.send_feedback()
                print("Feedback chunks: ", self.chunk_process)
                print("Feedback chunks num: ", len(self.chunk_process))
                print("Feedback idx: ", self.feedback_idx)
                self.feedback_idx += 1
                self.feedback_ack_flag = True

    # 定时器线程每隔1s记录收包数,即接收吞吐量
    def rx_save_throughput(self):
        if (self.recv_done_flag == False):
            self.rx_packid_save.append(self.rx_packet_id)
            self.rx_dropid_save.append(self.rx_drop_id)
            self.rx_creat_ttl_Timer()

    def rx_creat_ttl_Timer(self):
        if (self.recv_done_flag == False):
            t = threading.Timer(1, self.rx_save_throughput)
            t.start()

    # 计算接收瞬时吞吐量
    def rx_cal_ttl(self):
        idx = 0
        while idx < len(self.rx_packid_save):
            if idx == 0:
                self.rx_packs_per_sec.append(self.rx_packid_save[0])
            else:
                self.rx_packs_per_sec.append(self.rx_packid_save[idx] -
                                             self.rx_packid_save[idx - 1])
            idx += 1
        idx = 0
        while idx < len(self.rx_dropid_save):
            if idx == 0:
                self.rx_drops_per_sec.append(self.rx_dropid_save[0])
            else:
                self.rx_drops_per_sec.append(self.rx_dropid_save[idx] -
                                             self.rx_dropid_save[idx - 1])
            idx += 1

    def send_recv_done_ack(self):
        if self.recv_done_flag:
            self.acoustic.mfsk_tx_config()
            self.acoustic.mfsk_tx(b'#$\r\n')
            self.port.flushOutput()

    def send_feedback(self):
        self.acoustic.mfsk_tx_config()
        fb = b'$#' + self.process_bytes + b'\r\n'
        self.acoustic.mfsk_tx(fb)
        self.port.flushOutput()

    '''基于水声辅助的光通信链路建立部分'''

    # 等待水声握手,并反馈水声握手ACK
    def wait_acoustic_handshake(self):
        print("===...waiting for connection...===")
        self.acoustic.mfsk_rx_config()
        while True:
            str_recv = self.acoustic.mfsk_rx()
            # 收到水声握手包
            if str_recv[0:2] == "##":
                var = self.acoustic.acoustic_handshake_pack_res(str_recv[2:])
                # 反馈水声握手ACK
                if var[0] == self.ID:
                    self.acoustic.mfsk_tx_config()
                    self.acoustic.mfsk_tx(b'##snc')
                    self.snc_handshake_done = True
                    break

    # 下面3个是ROV可见光通信自动对准程序
    def rov_vlc_align(self):
        last_state = 1  #右转
        start = time.time()
        align_flag = False  #对准标志位
        print("===Start to align===")
        while not align_flag:
            align_flag = self.align_stability_test()
            if not align_flag:
                if self.align_rov_state == 0:
                    if (last_state == 1):
                        print("===Rov turn right===")
                        self.rov.port.write(b'#8868$')  #右转
                else:
                    if (last_state == 0):
                        print("===Rov turn left===")
                        self.rov.port.write(b'#88a8$')  #左转
            last_state = self.align_rov_state
            #对准成功
            if align_flag:
                print('===Align Successed!===')
                print("===Sending VLC handshake ACK===")
                self.vlc_handshake_done = True
                self.acoustic.mfsk_tx_config()
                self.acoustic.mfsk_tx(b'$$vlc')
                break
            #超过30s,对准失败
            elif (time.time() - start) > 30:
                print('===Align Failed!===')
                self.vlc_handshake_done = False
                break

    # 稳定性测试
    def align_stability_test(self):
        if self.align_vlc_rx():  #当前时刻能接收光信号
            if self.align_rov_state == 0:  #记录旋转状态,如因惯性过转,下次反转
                self.align_rov_state = 1
            else:
                self.align_rov_state = 0
            print("===Rov stop===")
            self.rov.port.write(b'#0000$')  #rov停转
            time.sleep(1)
            #静止后仍然能接收光信号
            print("===stop and receive===")
            rnum = 0
            start = time.time()
            while True:
                if (self.align_vlc_rx()):
                    rnum += 1
                    print("rnum = ", rnum)
                if (time.time() - start) > 3:
                    if (rnum > 24):
                        return True
                    else:
                        return False
        else:
            return False

    # 接收可见光通信探测包并检测
    def align_vlc_rx(self):
        a_drop_bytes = self.catch_a_drop_spi()
        if a_drop_bytes is not b'':
            check_data = recv_check(a_drop_bytes)
            if check_data is not b'':
                print("Receive a valid packet!!!")
                return True
            else:
                return False
        else:
            return False

    '''中继转发部分'''

    def relay_forward(self):
        # 状态重新初始化
        self.align_rov_state = 0
        self.vlc_handshake_done = False
        self.snc_handshake_done = False
        self.vlc_handshake_timedout = False
        # 中继转发
        print(
            '========================================================================'
        )
        print(
            'INFO: srcID=0, selfID=1, desID=2, starting Relay Forwarding procedure...'
        )
        self.send_acoustic_handshake()
        self.wait_acoustic_handshake_ACK()
        if self.snc_handshake_done == True:
            self.rov_vlc_align()
            if self.vlc_handshake_done:
                time.sleep(3)
                print("===Starting data relay forwarding transfer===")
                self.fountain = EW_Fountain(self.img_recv_bits, chunk_size=215)
                self.send_drops_spi()
        else:
            print(
                "Acoustic handshake failed, Relay Forwarding Transmission Terminated !!!"
            )

    # 寻找下一跳节点id
    def find_next_id(self):
        idx = 0
        next_id = 0
        for id in self.routing_table:
            if id == self.ID:
                next_id = self.routing_table[idx + 1]
                return next_id
            idx += 1
        return None

    # 发送水声握手包
    def send_acoustic_handshake(self):
        id = self.find_next_id()
        if id is not None:
            nextid = format(int(id), "08b")
            srcid = format(int(0), "08b")
            desid = format(int(2), "08b")
            w1size = format(int(6), "08b")
            imgW = format(int(256), "016b")
            imgH = format(int(256), "016b")
            SPIHTlen = format(int(len(self.m)), "032b")
            level = format(int(3), "08b")
            wavelet = format(int(1), "08b")  # 1代表bior4.4
            mode = format(int(1), "08b")  # 1代表periodization
            acoustic_handshake = b'##' + bitarray.bitarray(
                nextid + srcid + desid + w1size + imgW + imgH + SPIHTlen +
                level + wavelet + mode).tobytes()
            # 切换成发送模式,发送水声握手包
            print('===Send desID=2 acoustic broadcast handshake===')
            self.acoustic.mfsk_tx_config()
            self.acoustic.mfsk_tx(acoustic_handshake)
        else:
            print("nextID Not Found !!!")

    # 等待水声握手包的ACK
    def wait_acoustic_handshake_ACK(self):
        self.acoustic.mfsk_rx_config()
        snc_shake_time0 = time.time()
        snc_shake_retry_times = 0
        while True:
            if self.acoustic.mfsk_rx() == "##snc":
                print(
                    '===Acoustic handshake ACK received, Acoustic handshake done!==='
                )
                self.snc_handshake_done = True
                break
            if (time.time() - snc_shake_time0) % 6 == 0:
                self.send_acoustic_handshake()
                snc_shake_retry_times += 1
                if snc_shake_retry_times >= 3:
                    break

    # 中继转发喷泉码
    def a_drop(self):
        return self.fountain.droplet().toBytes()

    def send_drops_spi(self):
        # 启动反馈检测、吞吐量计算线程
        self.tx_creat_ttl_Timer()
        self.creat_detect_feedback_Timer()
        # 主线程
        while True:
            self.tx_drop_id += 1
            # 发送一帧补0到239字节
            sendbytes = send_check(self.a_drop())
            sendbytearray = bytearray(sendbytes)
            datalen = len(sendbytearray)
            while (datalen < 239):
                sendbytearray.insert(datalen, 0)
                datalen += 1

            self.spiSend.xfer2(sendbytearray)
            print("====================")
            print("Relay Forward Send dropid: ", self.tx_drop_id)
            print("====================")
            print("FountainFrameLen: ", len(self.a_drop()))
            print("SendFrameLen: ", len(sendbytearray))

            if (self.recvdone_ack):
                logging.info('============Fountain Send done===========')
                logging.info('Send drops used: ' + str(self.tx_drop_id))
                logging.info('Feedback num: ' + str(self.feedback_num))

                # 记录吞吐量
                throughput_list = cal_ttl(self.tx_dropid_save)
                # print('dropid history: ', self.dropid_save, len(self.dropid_save))
                print('drops_per_sec: ', throughput_list, len(throughput_list))
                res = pd.DataFrame({
                    'dropid_history': self.tx_dropid_save,
                    'drops_per_sec': throughput_list
                })
                res.to_csv(
                    ('data_save/Send_ttl' + '_' +
                     time.asctime().replace(' ', '_').replace(':', '_') +
                     '.csv'),
                    mode='a')
                break

            time.sleep(0.09)  #发包间隔

    # 定时器线程每隔1s记录发包数,即吞吐量
    def tx_save_throughput(self):
        if (self.recvdone_ack == False):
            self.tx_dropid_save.append(self.tx_drop_id)
            self.tx_creat_ttl_Timer()

    def tx_creat_ttl_Timer(self):
        if (self.recvdone_ack == False):
            t = threading.Timer(1, self.tx_save_throughput)
            t.start()

    # 检测反馈
    def feedback_detect(self):
        data_rec = self.acoustic.modem_feedback()
        if data_rec is not b'':
            data_str = str(data_rec, encoding="utf8")
            idx = data_str.find('Received String: ')
            if idx >= 0:
                msg_str = data_str[idx + 17:]
                msg_bytes = bytes(msg_str, encoding="utf-8")

                # msg_bytes = data_rec
                # 接收完成
                if msg_bytes[:2] == b'#$':
                    self.recvdone_ack = True
                # 进度包
                elif msg_bytes[:2] == b'$#':
                    self.fountain.all_at_once = True
                    process_recv = self.get_process_from_feedback(msg_bytes)
                    if process_recv == []:
                        self.recvdone_ack = True
                    else:
                        self.chunk_process = process_recv
                        self.fountain.chunk_process = self.chunk_process
                        self.fountain.feedback_idx = self.feedback_num
                        self.feedback_num += 1
        self.creat_detect_feedback_Timer()

    def creat_detect_feedback_Timer(self):
        if self.recvdone_ack == False:
            t = threading.Timer(0.001, self.feedback_detect)
            t.start()

    # 从反馈中获取进度
    def get_process_from_feedback(self, rec_bytes):
        process = []
        chunk_id = 0
        process_bits = bitarray.bitarray(endian='big')
        process_bits.frombytes(rec_bytes[2:])
        while chunk_id < self.fountain.num_chunks:
            if (process_bits[chunk_id] == False):
                process.append(chunk_id)
            chunk_id += 1
        return process
Ejemplo n.º 4
0
class EW_Receiver(Receiver):
    def __init__(self, port, baudrate, timeout, recv_img=None):
        Receiver.__init__(self, port=port, baudrate=baudrate, timeout=timeout)

    def add_a_drop(self, d_byte):
        a_drop = self.glass.droplet_from_Bytes(d_byte)
        print("seed: {}\tnum_chunk : {}\tdata len: {}".format(
            a_drop.seed, a_drop.num_chunks, len(a_drop.data)))
        ew_drop = EW_Droplet(a_drop.data, a_drop.seed, a_drop.num_chunks)

        if self.glass.num_chunks == 0:
            self.wlt_ds = time.time()
            print('init num_chunks : ', a_drop.num_chunks)
            self.glass = Glass(a_drop.num_chunks)
            self.chunk_size = len(a_drop.data)

        self.glass.addDroplet(ew_drop)

        logging.info('current chunks')
        logging.info(
            [ii if ii == None else '++++' for ii in self.glass.chunks])

        # 解码w1信息
        w1_size = 0.1
        if self.glass.is_w1_done(w1_size) and self.w1_done:
            print('w1_data complete!')
            w1_bits = self.glass.get_w1_bits(
                int(round(self.glass.num_chunks * w1_size)))
            self.w1_done = False
            if (int(w1_bits.length()) > 0) and \
                    (w1_bits.length() > self.current_recv_bits_len):
                self.current_recv_bits_len = w1_bits.length()
                self.i_spiht = self.w1_123(w1_bits)

                try:
                    self.i_dwt[0] = spiht_decode(self.i_spiht[0], self.eng)
                    self.i_dwt[1] = spiht_decode(self.i_spiht[1], self.eng)
                    self.i_dwt[2] = spiht_decode(self.i_spiht[2], self.eng)
                    self.img_mat = [func_IDWT(ii) for ii in self.i_dwt]

                    #  单通道处理
                    #  self.idwt_coeff_r = spiht_decode(self.recv_bit, self.eng)
                    #  self.r_mat =func_IDWT(self.idwt_coeff_r)
                    self.img_shape = self.img_mat[0].shape
                    self.show_recv_img()
                except:
                    print('decode error in matlab')

        # 解码全部信息
        if self.glass.isDone():  # 喷泉码接收译码完成
            wlt_de = time.time()
            print('Window LT decode time used:', wlt_de - self.wlt_ds)
            self.recv_bit = self.glass.get_bits()
            #  print('recv bits length : ', int(self.recv_bit.length()))
            if (int(self.recv_bit.length()) > 0) and \
                    (self.recv_bit.length() > self.current_recv_bits_len):
                self.current_recv_bits_len = self.recv_bit.length()
                self.i_spiht = self._123(self.recv_bit)
                try:
                    spihtstart = time.time()
                    self.i_dwt[0] = spiht_decode(self.i_spiht[0], self.eng)
                    self.i_dwt[1] = spiht_decode(self.i_spiht[1], self.eng)
                    self.i_dwt[2] = spiht_decode(self.i_spiht[2], self.eng)
                    self.img_mat = [func_IDWT(ii) for ii in self.i_dwt]
                    spihtend = time.time()
                    print('SPIHT decode time:', spihtend - spihtstart)
                    #  单通道处理
                    #  self.idwt_coeff_r = spiht_decode(self.recv_bit, self.eng)
                    #  self.r_mat =func_IDWT(self.idwt_coeff_r)
                    self.img_shape = self.img_mat[0].shape
                    self.show_recv_img()
                    self.recv_done_flag = True
                    self.send_recv_done_ack()
                except:
                    print('decode error in matlab')
Ejemplo n.º 5
0
def sim_ber():
    test_dir = os.path.join(SIM_PATH, 'sim_ber')
    if not os.path.exists(test_dir):
        os.mkdir(test_dir)

    chunk_size = 40
    loop_num = 5
    chunk_num = ceil(len(m) / float(chunk_size))

    p1 = 0.4
    ber = np.arange(0.0001, 0.015, 0.001)
    code_rate = [0] * len(ber)
    w1_size = 0.4
    w1_done = [0] * len(ber)
    w2_done = [0] * len(ber)
    per_list = [0] * len(ber)
    raw_data_size = len(m)
    i = 0
    for ber_ in tqdm(ber):
        print(heap)
        fountain = EW_Fountain(m,
                               chunk_size=chunk_size,
                               w1_size=w1_size,
                               w1_pro=p1)
        for j in tqdm(range(loop_num)):
            glass = Glass(fountain.num_chunks)
            drop_id = 0
            PER = 1 - (1 - ber_)**(chunk_size * 8)
            w1_done_t = 0
            while (not glass.isDone()):
                # print(drop_id * float(chunk_size) / len(m))
                drop_id += 1
                a_drop = fountain.droplet()
                ew_drop = EW_Droplet(a_drop.data,
                                     a_drop.seed,
                                     a_drop.num_chunks,
                                     w1_size,
                                     w1_pro=p1)
                glass.addDroplet(ew_drop)
                if glass.is_w1_done(w1_size) and w1_done_t == 0:
                    w1_done_t = drop_id
                del a_drop
                del ew_drop
                if (drop_id * chunk_size / raw_data_size > 50):
                    print("_")
            code_rate[i] += chunk_size * drop_id / (1 - PER)
            w1_done[i] += w1_done_t * chunk_size / (1 - PER)
            w2_done[i] += drop_id * chunk_size / (1 - PER)
            per_list[i] = PER
            del glass
        del fountain
        i += 1
    code_rate = [float(ii) / (len(m) * loop_num) for ii in code_rate]
    w1_done = [float(ii) / (len(m) * loop_num) for ii in w1_done]
    w2_done = [float(ii) / (len(m) * loop_num) for ii in w2_done]
    df_res = pd.DataFrame({
        "ber": ber,
        "code_rate": code_rate,
        'w1_done': w1_done,
        'w2_done': w2_done,
        'per': [1 - (1 - ii)**(8 * chunk_size) for ii in ber],
        'loop_num': [loop_num for ii in ber],
        'chunk_size': [chunk_size for ii in ber],
        'p1': [p1 for ii in ber],
        'chunk_num': [chunk_num for ii in ber],
        'w1_size': [w1_size for ii in ber]
    })
    res_file = os.path.join(
        test_dir,
        time.asctime().replace(' ', '_').replace(
            ':', '_')) + "_" + str(p1) + "_" + str(chunk_size) + '.csv'
    df_res.to_csv(res_file)
    print(df_res)
    return res_file
Ejemplo n.º 6
0
def sim_diff_psnr():
    test_dir = os.path.join(SIM_PATH, 'sim_diff_psnr')
    if not os.path.exists(test_dir):
        os.mkdir(test_dir)
    res_file = os.path.join(test_dir,
                            time.asctime().replace(' ', '_').replace(
                                ':', '_')) + '.csv'

    need_lest = 79
    packet_ceil = 631
    deli_rate = pkl.load(open(os.path.join(SIM_PATH, 'deil.pkl'), 'rb'))
    loop_num = 1000
    m = ' ' * need_lest
    p1_list = list(np.arange(0.1, 0.9, 0.1))
    w1_list = list(np.arange(0.1, 0.9, 0.1))
    res_size = len(p1_list) * len(w1_list)

    res_w1 = [0] * res_size
    for i in range(res_size):
        res_w1[i] = w1_list[int(i / len(p1_list))]
    res = pd.DataFrame({
        "w1": res_w1,
        'p1': p1_list * len(w1_list),
        # 'w1_done' : [0] * res_size,
        # "all_done": [0] * res_size
    })

    w1_done_tmp = [0] * res_size
    all_done_tmp = [0] * res_size
    i = 0
    for w1 in tqdm(w1_list):
        j = 0
        for p1 in tqdm(p1_list):
            all_done = 0
            res_index = i * len(p1_list) + j
            for loop in tqdm(range(loop_num)):
                fountain = EW_Fountain(m, chunk_size=1, w1_size=w1, w1_pro=p1)
                glass = Glass(fountain.num_chunks)
                w1_done = 0
                for drop_id in range(packet_ceil):
                    a_drop = fountain.droplet()
                    ew_drop = EW_Droplet(a_drop.data, a_drop.seed,
                                         a_drop.num_chunks, w1, p1)
                    glass.addDroplet(ew_drop)
                    if glass.is_w1_done(w1) and w1_done == 0:
                        w1_done_tmp[res_index] += drop_id
                        w1_done = 1
                        # print("w1 done at {}".format(drop_id))
                    elif glass.isDone():
                        # print("all done at {}".format(drop_id))
                        all_done_tmp[res_index] += drop_id
                        break
            w1_done_tmp[res_index] = w1_done_tmp[res_index] / float(loop_num)
            all_done_tmp[res_index] = all_done_tmp[res_index] / float(loop_num)
            j += 1
        i += 1
    res['w1_done'] = w1_done_tmp
    res['all_done'] = all_done_tmp
    res = res[['w1', 'p1', 'w1_done', 'all_done']]
    print(res)
    res.to_csv(res_file)
Ejemplo n.º 7
0
def sim_p1():
    test_dir = os.path.join(SIM_PATH, 'sim_p1')
    res_file = os.path.join(test_dir,
                            time.asctime().replace(' ', '_').replace(
                                ':', '_')) + '.csv'
    step = 0.05
    floor = 0.3
    ceiling = 0.7
    p1_list = list(np.arange(floor, ceiling, step))
    p1_list.reverse()
    code_rate = [0] * len(p1_list)
    w1_size = 0.5
    w1_done = [0] * len(p1_list)
    w2_done = [0] * len(p1_list)
    per_list = [0] * len(p1_list)
    chunk_size = 255
    loop_num = 50
    chunk_num = ceil(len(m) / float(chunk_size))
    BER = 0.0001
    i = 0
    for p1 in tqdm(p1_list):
        for j in tqdm(range(loop_num)):
            fountain = EW_Fountain(m,
                                   chunk_size=chunk_size,
                                   w1_size=w1_size,
                                   w1_pro=p1)
            glass = Glass(fountain.num_chunks)
            drop_id = 0
            PER = 1 - (1 - BER)**(chunk_size * 8)
            w1_done_t = 0
            while not glass.isDone():
                drop_id += 1
                a_drop = fountain.droplet()
                ew_drop = EW_Droplet(a_drop.data,
                                     a_drop.seed,
                                     a_drop.num_chunks,
                                     w1_size,
                                     w1_pro=p1)
                glass.addDroplet(ew_drop)
                if glass.is_w1_done(w1_size) and w1_done_t == 0:
                    w1_done_t = drop_id
                del a_drop
                del ew_drop
            code_rate[i] += chunk_size * drop_id / (1 - PER)
            w1_done[i] += w1_done_t * chunk_size / (1 - PER)
            w2_done[i] += drop_id * chunk_size / (1 - PER)
            per_list[i] = PER
            del fountain
            del glass
        i += 1
    code_rate = [float(ii) / (len(m) * loop_num) for ii in code_rate]
    w1_done = [float(ii) / (len(m) * loop_num) for ii in w1_done]
    w2_done = [float(ii) / (len(m) * loop_num) for ii in w2_done]
    df_res = pd.DataFrame({
        "p1": p1_list,
        "code_rate": code_rate,
        'w1_done': w1_done,
        'w2_done': w2_done,
        'per': per_list,
        'loop_num': [loop_num for ii in p1_list],
        'chunk_size': [chunk_size for ii in p1_list],
        'chunk_num': [chunk_num for ii in p1_list],
        'w1_size': [w1_size for ii in p1_list]
    })
    df_res.to_csv(res_file)
    print(df_res)
    return res_file