Example #1
0
class EW_Receiver(Receiver):
    def __init__(self, recv_img=None):
        Receiver.__init__(self)

    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:
            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)
        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, self.chunk_size)
            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')
Example #2
0
class Receiver:
    def __init__(self, port,
                 baudrate,
                 timeout,
                 ):

        self.port = serial.Serial(port, baudrate)
        # if (self.port.is_open):
        #     print("串口{}打开成功".format(self.port.portstr))
        # else:
        #     print("串口打开失败")

        self.eng = matlab.engine.start_matlab()
        self.eng.addpath(LIB_PATH)

        self.drop_id = 0
        self.glass = Glass(0)
        self.chunk_size = 0
        self.current_recv_bits_len = 0
        self.i_spiht = []
        self.i_dwt = [[], [], []]
        self.img_mat = []
        #  暂时
        self.idwt_coeff_r = None
        self.r_mat = None
        self.img_shape = [0, 0]
        self.recv_img = None
        self.drop_byte_size = 99999
        self.test_dir = os.path.join(TEST_PATH, time.asctime().replace(' ', '_').replace(':', '_'))
        # os.mkdir(self.test_dir)


        # while True:
        #     self.begin_to_catch()
        #     if self.glass.isDone():
        #
        #         print('recv done')
        #         break

    def begin_to_catch(self):
        a_drop = self.catch_a_drop_use_serial()
        if not a_drop == None:
            self.drop_id += 1
            print("drops id : ", self.drop_id)
            self.drop_byte_size = len(a_drop)
            self.add_a_drop(a_drop)

    data_rec =''

    def catch_a_drop_use_serial(self):
        # size = self.port.in_waiting
        # if size:
        self.data_rec = self.port.read()
        a = len(self.data_rec)
        return self.data_rec

    def add_a_drop(self, d_byte):
        drop = self.glass.droplet_from_Bytes(d_byte)

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

        self.glass.addDroplet(drop)

        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 = int(self.recv_bit.length())
            #  self.recv_bit.tofile(open('./recv_tmp.txt', 'w'))
            self.i_spiht = self._123(self.recv_bit, self.chunk_size)
            #  self.i_dwt = [spiht_decode(ii, self.eng) for ii in self.i_spiht]
            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')

    def show_recv_img(self):
        if self.recv_img == None:
            self.recv_img = Image.new('RGB', (self.img_shape[0], self.img_shape[0]), (0, 0, 20))
        for i in range(self.img_shape[0]):
            for j in range(self.img_shape[0]):
                R = self.img_mat[0][i, j]
                G = self.img_mat[1][i, j]
                B = self.img_mat[2][i, j]

                #  单通道处理
                #  G = self.r_mat[i, j]
                #  G = 255
                #  B = 255
                new_value = (int(R), int(G), int(B))
                self.recv_img.putpixel((i, j), new_value)
        self.recv_img.show()
        self.recv_img.save(os.path.join(self.test_dir, str(self.drop_id)) + ".bmp")

    def _123(self, bits, chunk_size):                          # 将rgb拆成r,g,b
        self.recv_bit_len = int(bits.length())
        i_spiht_list = []
        #  if bits % 3 == 0:
        #  print('')
        # chunk_size = self.chunk_size
        chunk_size = self.glass.chunk_bit_size
        print('self.glass.chunk_bit_size : ', self.glass.chunk_bit_size)
        #  bits.tofile(open(str(self.drop_id), 'w'))
        each_chunk_size = chunk_size / 3
        r_bits = bitarray.bitarray('')
        g_bits = bitarray.bitarray('')
        b_bits = bitarray.bitarray('')
        print('recv_bit len : ', bits.length())

        for i in range(int(ceil(int(bits.length()) / float(chunk_size)))):
            start = i * chunk_size
            end = min((i + 1) * chunk_size, int(bits.length())) * 8
            tap_chunk = bits[start: end]
            r_bits += tap_chunk[each_chunk_size * 0: each_chunk_size * 1]
            g_bits += tap_chunk[each_chunk_size * 1: each_chunk_size * 2]
            b_bits += tap_chunk[each_chunk_size * 2: each_chunk_size * 3]
        rgb = list('rgb')
        #  r_bits.tofile(open("r_"+str(self.drop_id), 'w'))
        rgb_bits = [r_bits, g_bits, b_bits]
        return rgb_bits
Example #3
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 Receiver:
    def __init__(
        self,
        bus,
        device,
    ):
        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_init()

        self.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(':', '_'))

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

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

        if a_drop_bytes is not None:
            self.drop_id += 1
            print("====================")
            print("Recv dropid : ", self.drop_id)
            print("====================")
            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

    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 !')

    def add_a_drop(self, d_byte):
        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(drop)  # glass add drops

        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
            logging.info('============Recv done===========')
            # 接收完成写入图像
            img_data = self.glass.get_bits()
            os.mkdir(self.recv_dir)
            with open(os.path.join(self.recv_dir, "img_recv" + ".jpg"),
                      'wb') as f:
                f.write(img_data)
            self.send_recv_done_ack()  # 接收完成返回ack

        # 接收到K个数据包之后
        if self.drop_id >= self.glass.num_chunks:
            if (self.drop_id - self.glass.num_chunks) % 10 == 0:
                self.chunk_process = self.glass.getProcess()  # 用于返回进程包
                self.glass.glass_process_history.append(
                    self.chunk_process)  # 添加反馈历史数据,用于droplet参数,正确译码
                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

    def send_recv_done_ack(self):
        if self.recv_done_flag:
            ack = b'#$'
            acklen = len(ack)
            acksend = bytearray(ack)
            while (acklen < 239):
                acksend.insert(acklen, 0)
                acklen += 1
            self.spiSend.xfer2(acksend)
            logging.info('Send fountain ACK done')
            logging.info('Recv drops: ' + str(self.drop_id))
            logging.info('Wrong frame drops: ' + str(self.drop_id))
            logging.info('Wrong checksum drops: ' + str(self.drop_id))

    def send_feedback(self):
        fb = b'$#'
        for chunk_id in self.chunk_process:
            chunk_id_bits = format(int(chunk_id), "016b")
            fb += bitarray.bitarray(chunk_id_bits).tobytes()

        fblen = len(fb)
        fbsend = bytearray(fb)
        while (fblen < 239):
            fbsend.insert(fblen, 0)
            fblen += 1
        self.spiSend.xfer2(fbsend)
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
Example #6
0
class Receiver:
    def __init__(
        self,
        port,
        baudrate,
        timeout,
    ):

        self.port = serial.Serial(port, baudrate)
        # if (self.port.is_open):
        #     print("串口{}打开成功".format(self.port.portstr))
        # else:
        #     print("串口打开失败")

        self.eng = matlab.engine.start_matlab()
        self.eng.addpath(LIB_PATH)

        self.drop_id = 0
        self.glass = Glass(0)
        self.chunk_size = 0
        self.current_recv_bits_len = 0
        self.i_spiht = []
        self.i_dwt = [[], [], []]
        self.img_mat = []
        #  暂时
        self.idwt_coeff_r = None
        self.r_mat = None
        self.img_shape = [0, 0]
        self.recv_img = None
        self.drop_byte_size = 99999
        self.test_dir = os.path.join(
            TEST_PATH,
            time.asctime().replace(' ', '_').replace(':', '_'))
        self.w1_done = True
        self.recv_done_flag = False
        self.wlt_ds = 0
        self.detect_done = False

    '探测序列检测部分,检测完成返回ack'

    def detect_exam(self):
        success_times = 0
        recv_id = 0
        while recv_id < 10:
            recv_bytes = self.catch_a_drop_use_serial()

            if recv_bytes is not None:
                recv_id += 1
                print('recv id:', recv_id)
                results = recv_check(recv_bytes)
                if not results == None:
                    success_times += 1
                    print('success rate:{}/{}'.format(success_times, recv_id))

        success_rate = float(success_times / 10)
        if success_rate > 0.5:
            self.detect_done = True

        self.send_detect_ack()

    def send_detect_ack(self):
        ack_good = b'ok'
        ack_bad = b'no'
        if self.detect_done:
            self.port.write(ack_good)
            self.port.flushOutput()
        else:
            self.port.write(ack_bad)
            self.port.flushOutput()
        print('send detect ack done')

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

    def begin_to_catch(self):

        a_drop_bytes = self.catch_a_drop_use_serial()  # bytes

        if a_drop_bytes is not None:
            check_data = recv_check(a_drop_bytes)

            # if check_data is None:
            #     self.begin_to_catch()
            # else:
            if not check_data == None:
                self.drop_id += 1
                print("recv drops id : ", self.drop_id)
                self.drop_byte_size = len(check_data)
                self.add_a_drop(check_data)  # bytes --- drop --- bits

    data_rec = ''

    def catch_a_drop_use_serial(self):
        time.sleep(1)
        size1 = self.port.in_waiting
        if size1:
            self.data_rec = self.port.read_all()
            frame_len = len(self.data_rec)
            if self.data_rec[0:2] == b'ok' and self.data_rec[
                    frame_len - 4:frame_len] == b'fine':
                data_array = bytearray(self.data_rec)
                data_array.pop(0)
                data_array.pop(0)
                data_array.pop()
                data_array.pop()
                data_array.pop()
                data_array.pop()
                a = len(bytes(data_array))
                print('drop len(crc) :', a)

                return bytes(data_array)
            else:
                print('Wrong receive frame !')
        else:
            self.port.flushInput()

    def add_a_drop(self, d_byte):
        recv_time_start = time.time()
        drop = self.glass.droplet_from_Bytes(d_byte)  # drop

        print('drop data len: ', len(drop.data))

        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)

        lt_decode_start = time.time()
        self.glass.addDroplet(drop)  # glass add drops

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

        if self.glass.isDone():
            lt_decode_end = time.time()
            print('LT decode time:', lt_decode_end - lt_decode_start)

            self.recv_bit = self.glass.get_bits()  # bits

            # a = self.recv_bit.length()
            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 = int(self.recv_bit.length())

                self.i_spiht = self._123(self.recv_bit)
                try:
                    SPIHT_time_start = 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]
                    SPIHT_time_end = time.time()
                    print('SPIHT decode time:',
                          SPIHT_time_end - SPIHT_time_start)
                    print('recv time total cost:',
                          SPIHT_time_end - recv_time_start)

                    #  单通道处理
                    #  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')

    def show_recv_img(self):
        if self.recv_img == None:
            self.recv_img = Image.new('RGB',
                                      (self.img_shape[0], self.img_shape[0]),
                                      (0, 0, 20))
        for i in range(self.img_shape[0]):
            for j in range(self.img_shape[0]):
                R = self.img_mat[0][i, j]
                G = self.img_mat[1][i, j]
                B = self.img_mat[2][i, j]

                #  单通道处理
                #  G = self.r_mat[i, j]
                #  G = 255
                #  B = 255
                new_value = (int(R), int(G), int(B))
                self.recv_img.putpixel((i, j), new_value)
        self.recv_img.show()
        self.recv_img.save(
            os.path.join(self.test_dir, str(self.drop_id)) + ".bmp")

    def _123(self, bits):  # 将rgb拆成r,g,b
        self.recv_bit_len = int(bits.length())
        i_spiht_list = []
        #  if bits % 3 == 0:
        #  print('')
        # chunk_size = self.chunk_size
        rgb_chunk_bit_size = 12000
        print('self.glass.chunk_bit_size : ', self.glass.chunk_bit_size)
        #  bits.tofile(open(str(self.drop_id), 'w'))
        each_chunk_size = int(rgb_chunk_bit_size / 3)
        r_bits = bitarray.bitarray('')
        g_bits = bitarray.bitarray('')
        b_bits = bitarray.bitarray('')
        print('recv_bit len : ', bits.length())

        for i in range(
                int(ceil(int(bits.length()) / float(rgb_chunk_bit_size)))):
            start = i * rgb_chunk_bit_size
            end = min((i + 1) * rgb_chunk_bit_size, int(bits.length()))
            tap_chunk = bits[start:end]
            r_bits += tap_chunk[each_chunk_size * 0:each_chunk_size * 1]
            g_bits += tap_chunk[each_chunk_size * 1:each_chunk_size * 2]
            b_bits += tap_chunk[each_chunk_size * 2:]
        rgb = list('rgb')
        #  r_bits.tofile(open("r_"+str(self.drop_id), 'w'))
        rgb_bits = [r_bits, g_bits, b_bits]
        return rgb_bits

    def w1_123(self, w1_bits):  # 将rgb拆成r,g,b
        self.recv_bit_len = int(w1_bits.length())
        i_spiht_list = []
        #  if bits % 3 == 0:
        #  print('')
        # chunk_size = self.chunk_size
        rgb_chunk_bit_size = 12000
        print('self.glass.chunk_bit_size : ', self.glass.chunk_bit_size)

        each_chunk_bit_size = int(rgb_chunk_bit_size / 3)
        r_bits = bitarray.bitarray('')
        g_bits = bitarray.bitarray('')
        b_bits = bitarray.bitarray('')
        print('w1_bit len : ', w1_bits.length())

        num_rgb_chunks = int(
            ceil(int(w1_bits.length()) / float(rgb_chunk_bit_size)))
        rgb_bits_left = int(w1_bits.length() % rgb_chunk_bit_size)

        for i in range(num_rgb_chunks):
            start = i * rgb_chunk_bit_size
            end = min((i + 1) * rgb_chunk_bit_size, int(w1_bits.length()))
            tap_chunk = w1_bits[start:end]

            if i == num_rgb_chunks - 1 and rgb_bits_left < each_chunk_bit_size:
                r_bits += tap_chunk[each_chunk_bit_size * 0:]
                break

            elif i == num_rgb_chunks - 1 and each_chunk_bit_size < rgb_bits_left < each_chunk_bit_size * 2:
                r_bits += tap_chunk[each_chunk_bit_size *
                                    0:each_chunk_bit_size * 1]
                g_bits += tap_chunk[each_chunk_bit_size * 1:]
                break
            elif i == num_rgb_chunks - 1 and each_chunk_bit_size * 2 < rgb_bits_left < each_chunk_bit_size * 3:
                r_bits += tap_chunk[each_chunk_bit_size *
                                    0:each_chunk_bit_size * 1]
                g_bits += tap_chunk[each_chunk_bit_size *
                                    1:each_chunk_bit_size * 2]
                b_bits += tap_chunk[each_chunk_bit_size * 2:]

            r_bits += tap_chunk[each_chunk_bit_size * 0:each_chunk_bit_size *
                                1]
            g_bits += tap_chunk[each_chunk_bit_size * 1:each_chunk_bit_size *
                                2]
            b_bits += tap_chunk[each_chunk_bit_size * 2:]

        rgb = list('rgb')
        #  r_bits.tofile(open("r_"+str(self.drop_id), 'w'))
        rgb_bits = [r_bits, g_bits, b_bits]
        return rgb_bits

        # self.recv_bit_len = int(bits.length())
        # i_spiht_list = []
        # #  if bits % 3 == 0:
        # #  print('')
        # # chunk_size = self.chunk_size
        # bit_chunk_size = self.glass.chunk_bit_size
        #
        # print('self.glass.chunk_bit_size : ', self.glass.chunk_bit_size)
        # #  bits.tofile(open(str(self.drop_id), 'w'))
        # each_chunk_size = int(ceil(bit_chunk_size / 3))                         ###
        # # each_chunk_size = 2500                                              ###################
        # r_bits = bitarray.bitarray('')
        # g_bits = bitarray.bitarray('')
        # b_bits = bitarray.bitarray('')
        # print('recv_bit len : ', bits.length())
        #
        # for i in range(int(ceil(int(bits.length()) / float(bit_chunk_size)))):
        #     start = i * bit_chunk_size
        #     end = min((i + 1) * bit_chunk_size, int(bits.length()))                           ###*8
        #     tap_chunk = bits[start: end]
        #     r_bits += tap_chunk[each_chunk_size * 0: each_chunk_size * 1]
        #     g_bits += tap_chunk[each_chunk_size * 1: each_chunk_size * 2]
        #     b_bits += tap_chunk[each_chunk_size * 2:]
        # rgb = list('rgb')
        # #  r_bits.tofile(open("r_"+str(self.drop_id), 'w'))
        # rgb_bits = [r_bits, g_bits, b_bits]
        # return rgb_bits

    def send_recv_done_ack(self):
        if self.recv_done_flag:
            ack = b'recv'
            self.port.write(ack)
            self.port.flushOutput()
            print('send recv_done_ack done')

    '''RS接收解码部分'''

    def catch_rs_use_serial(self):
        time.sleep(1)
        size1 = self.port.in_waiting
        if size1 == 0:
            # print('\r', 'serial port listening......', end='')
            print('serial port listening......')
            self.catch_rs_use_serial()
        elif size1:
            self.data_rec = self.port.read_all()
            data_array = bytearray(self.data_rec)
            self.port.flushInput()

            return bytes(data_array)

    def rs_recv_main(self):
        recv_time_start = time.time()
        self.recv_byte = self.catch_rs_use_serial()

        if self.recv_byte is not None:
            rs_decode_start = time.time()
            rs_decoded = rs_decode_image(self.recv_byte)
            rs_decode_end = time.time()
            print('RS decode time:', rs_decode_end - rs_decode_start)
            bitarray_factory = bitarray.bitarray(endian='big')
            bitarray_factory.frombytes(rs_decoded)

            # if bitarray_factory is not None:
            # test = int(ceil(len(bitarray_factory) / 5))
            self.i_spiht = self._123(bitarray_factory)
            try:
                SPIHT_time_start = 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]
                SPIHT_time_end = time.time()
                print('SPIHT decode time:', SPIHT_time_end - SPIHT_time_start)
                self.img_shape = self.img_mat[0].shape
                self.show_recv_img()

                self.recv_done_flag = True
                recv_time_end = time.time()
                print('recv time total cost:', recv_time_end - recv_time_start)
                self.send_recv_done_ack()

            except:
                print('Decode error in matlab')
Example #7
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')
Example #8
0
class Receiver:
    def __init__(self, bus, device):
        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.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''

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

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

        if a_drop_bytes is not None:
            # 从收到第一个包之后,开启定时记录吞吐量线程,记录时间
            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

    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 !')

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

        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("VLC Feedback 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)

            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))
            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')

        # 反馈
        n1 = round(0.8 * self.glass.num_chunks)
        n2 = 30
        if self.drop_id >= n1 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]
                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
                self.feedback_send_done = True

        # if self.real_drop_id >= self.glass.num_chunks:
        #     if (self.real_drop_id - self.glass.num_chunks)%10==0 and self.feedback_send_done==False:
        #         self.chunk_process = self.glass.getProcess() # 用于返回进程包
        #         self.glass.glass_process_history.append(self.chunk_process) # 添加反馈历史数据,用于droplet参数,正确译码
        #         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

    def send_recv_done_ack(self):
        if self.recv_done_flag:
            ack = b'#$'
            acklen = len(ack)
            acksend = bytearray(ack)
            while (acklen < 239):
                acksend.insert(acklen, 0)
                acklen += 1
            self.spiSend.xfer2(acksend)
            logging.info('Send fountain ACK done')
            logging.info('Recv Packets: : ' + str(self.packet_id))
            logging.info('Recv drops: ' + str(self.drop_id))

    def send_feedback(self):
        fb = b'$#'
        for chunk_id in self.chunk_process:
            chunk_id_bits = format(int(chunk_id), "016b")
            fb += bitarray.bitarray(chunk_id_bits).tobytes()

        fblen = len(fb)
        fbsend = bytearray(fb)
        while (fblen < 239):
            fbsend.insert(fblen, 0)
            fblen += 1
        self.spiSend.xfer2(fbsend)
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.pack_id = 0
        self.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.t0 = 0
        self.t0_start = False
        self.t1 = 0
        self.process_bytes = b''

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

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

        if a_drop_bytes is not None:
            # 从接收到第一个包开始计时
            if self.t0_start == False:
                self.t0 = time.time()
                self.t0_start = True
            self.pack_id += 1
            print("Recv Packet_id : ", self.pack_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)

    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)

            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]

            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 drop_id : ", self.drop_id)
        print("====================")
        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)
        self.glass.addDroplet(ew_drop)  # glass add drops

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

        # 接收完成
        if self.glass.isDone():
            self.t1 = time.time()
            self.recv_done_flag = True
            # 接收完成写入图像
            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(2.6, self.send_recv_done_ack)
            t1.start()
            # self.send_recv_done_ack() # 接收完成返回ack
            logging.info('============Recv done===========')
            logging.info('Send Sonic Fountain ACK done')
            logging.info('Recv packets: ' + str(self.drop_id))
            logging.info('Recv drops: ' + str(self.drop_id))
            logging.info("Sonic Feedback Fountain time elapsed:" +
                         str(self.t1 - self.t0))

        # 接收到K个数据包之后
        n1 = round(0.8 * self.glass.num_chunks)
        n2 = 30
        if self.drop_id >= n1 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]
                process_bits = bitarray.bitarray(process_bitmap)
                self.process_bytes = process_bits.tobytes()

                t = threading.Timer(2.6, self.send_feedback)
                t.start()

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

    def send_recv_done_ack(self):
        if self.recv_done_flag:
            ack = b'#$\r\n'
            acksend = bytearray(ack)
            self.port.write(acksend)
            self.port.flushOutput()

    # 用定时器线程反馈仿真修改
    def send_feedback(self):
        fb = b'$#' + self.process_bytes
        self.port.write(fb)
        self.port.flushOutput()