예제 #1
0
 def begin_test(self):
     self.running = True
     self.endFuture = asyncio.Future()
     # 启动listen_to_t协程
     asyncio.run_coroutine_threadsafe(self.listen_to_t(),
                                      asyncio.get_event_loop())
     b4.send_line(self.tw, 'i=1')
예제 #2
0
    def handle_room_msg(self, room_id: int, msg: dict) -> bool:
        """
        处理房间发来的消息
        目前看来只有定时消息和关闭空调消息
        :param room_id: 发来消息的房间号
        :param msg: 消息
        :return: 如果关闭空调则返回False
        """
        room_info = self.rooms[room_id - 1]
        if 'tc' in msg.keys():
            msg_tc = int(msg['tc'])
            if 'it' in msg.keys():
                cur_t = int(msg['t'])
                print(
                    f'room={room_id} on={room_info.on} it={room_info.it} tt={room_info.tt} room_tc={room_info.tc}'
                )
                # 计费
                if room_info.on:
                    msg_tt = int(msg['tt'])
                    if msg_tt != room_info.tt or 'w' in msg:
                        if cur_t != room_info.tt:  # 没有保持目标温度
                            room_info.bill += abs(cur_t - room_info.it)
                            print('1: ' + str(abs(cur_t - room_info.it)))
                        else:
                            room_info.bill += abs(
                                room_info.tt - room_info.it) * (1 + msg_tc -
                                                                room_info.tc)
                            print('2: ' + str(
                                abs(room_info.tt - room_info.it) *
                                (1 + msg_tc - room_info.tc)))
                        # 重置
                        room_info.it = int(msg['it'])
                        room_info.tt = int(msg['tt'])
                else:
                    # 初始化
                    room_info.it = int(msg['it'])
                    room_info.tt = int(msg['tt'])
                if 'w' in msg.keys():
                    room_info.on = False
                    b4.send_line(self.tw, f'r={room_id} tc={msg_tc} w=0')
                    log.info(f'r={room_id} tc={msg_tc} w=0')
                    return False
                else:
                    room_info.on = True
            elif 't' in msg.keys():  # 定时信息
                # 如果尚未达到目标温度,则更新当前温度和tc
                if room_info.cur_t is None or room_info.cur_t != int(msg['t']):
                    room_info.cur_t = int(msg['t'])
                    room_info.tc = int(msg_tc)
                    log.info(
                        f"UPDATE: cur_t={room_info.cur_t}, tc={room_info.tc}")

                b4.send_line(self.tw, f'r={room_id} tc={msg_tc} t={msg["t"]}')
                log.info(f'r={room_id} tc={msg_tc} t={msg["t"]}')
        return True
예제 #3
0
    async def start(self):
        running = True
        step = 1
        while running:
            msg = await b4.recv_line(self.tr)
            if 'tc' in msg:
                self.cur_timer += 1  # 使原来的定时器无效
                msg_tc = int(msg['tc'])
                if 'ts' in msg:
                    self.ts = float(msg['ts'])

                # 校正当前温度
                dt = int((msg_tc - self.begin_tc) / (4 - self.w)) * step
                if abs(dt) > abs(self.tt - self.it):
                    t = self.tt
                else:
                    t = self.it + dt

                if 'w' in msg:
                    self.w = int(msg['w'])
                    self.it = t
                if 'tt' in msg:
                    self.tt = int(msg['tt'])
                    self.it = int(msg['it'])
                    step = 1 if self.tt > self.it else -1

                if self.w == 0:
                    b4.send_line(
                        self.sw,
                        f'tc={msg_tc} it={self.it} tt={self.tt} t={t} w=0')
                    running = False
                else:
                    b4.send_line(
                        self.sw,
                        f'tc={msg_tc} it={self.it} tt={self.tt} t={t}')
                    self.begin_tc = msg_tc
                    asyncio.run_coroutine_threadsafe(
                        self.timer(self.begin_tc, self.cur_timer),
                        asyncio.get_event_loop())
        try:  # 监听连接,等待服务器关闭连接,关闭后抛出异常即可结束协程
            await b4.recv_line(self.sr)
        except Exception as e:
            log.info('Close the server connection')
            print(e)
        self.close()
예제 #4
0
 async def login(self, host: str, port: int, k: str) -> bool:
     """
     服务器登录到test的协程
     :param host: test的host
     :param port: test的端口
     :param k: 密钥
     :return: 登录成功返回True
     """
     try:
         self.tr, self.tw = await asyncio.open_connection(host, port)
         b4.send_line(self.tw, f'k={k} r=s')
         rl = await b4.recv_line(self.tr, 'e')
         log.info("Server Login")
         return len(rl) == 1 and rl[0] == '0'
     except Exception as e:
         print(e)
     self.close()
     return False
예제 #5
0
 async def listen_to_t(self):
     while self.roomLoggedIn > 0:  # 仍有房间没有测试完成
         rl = await b4.recv_line(self.tr, 'b', 'tc')
         log.info(f"Received billing: {rl}")
         room_id = int(rl[0])  # 房间号
         if 1 <= room_id <= len(self.rooms):
             tc = int(rl[1])
             log.info(f"Check enter loop: tc={tc} room_id={room_id}")
             room_info = self.rooms[room_id - 1]
             # 返回"r={房间号} tc={tc} b={费用}"
             b4.send_line(self.tw,
                          f'r={room_id} tc={tc} b={room_info.bill}')
             log.info(
                 f'Send to test: r={room_id} tc={tc} b={room_info.bill}')
             self.rooms[room_id - 1] = None  # 房间测试通过,标记为登出
             self.roomLoggedIn -= 1
     print('测试结束,按回车退出')
     input()
     self.endFuture.set_result(1)  # 全部完成,允许连接断开
     asyncio.get_event_loop().stop()  # 消息循环可以结束
     self.close()  # 断开与test的连接
예제 #6
0
 async def _client_connected(self, r: asyncio.StreamReader,
                             w: asyncio.StreamWriter):
     """
     房间连接回调协程,连接建立后此协程处理该房间整个测试流程
     :param r: 房间到服务器的tcp输入流
     :param w: 服务器到房间的tcp输出流
     :return:
     """
     peer_host, peer_port, *_ = w.get_extra_info('peername')
     room_id = 0
     try:
         msg = await b4.recv_line(r, 'r')
         room_id = int(msg[0])
         log.info(f'msg:{msg}')
         if 1 <= room_id <= len(
                 self.rooms) and self.rooms[room_id - 1] is None:
             # 房间号在规定范围内且没有重复,成功登录
             b4.send_line(w, 'e=0')
             self.rooms[room_id - 1] = RoomInfo(r, w)  # 添加房间信息
             self.roomLoggedIn += 1
             if self.roomLoggedIn == len(self.rooms):  # 所有房间都已登录,开始测试
                 log.info("All room logged in, begin test...")
                 self.begin_test()
             while True:
                 msg = await b4.recv_line(r)  # 取一个消息
                 log.info(f'handling msg:{msg}')
                 if not self.handle_room_msg(room_id, msg):
                     break
         else:  # 非法房间号
             b4.send_line(w, 'e=InvalidRoom')
     except Exception as e:
         print(e)
     # 测试还没开始到达此处,表示房间登录失败,清除记录
     if not self.running and 1 <= room_id <= len(self.rooms):
         self.rooms[room_id - 1] = None
         self.roomLoggedIn -= 1
     if self.endFuture:  # 还有房间没有完成,等结束后再断开连接
         await self.endFuture
         self.endFuture = None
     w.close()
예제 #7
0
    async def timer(self, tc, timer_id):
        """
        定时更新状态及发送消息的协程
        """
        t = self.it  # 当前温度
        time_step = 1 if self.it < self.tt else -1
        log.info(f"it={self.it} up={time_step}")
        log.info(f"w is {self.w}")
        while self.cur_timer == timer_id:  # 当前定时器有效
            b4.send_line(self.sw, f'tc={tc} t={t}')
            log.info(f'Send to server: tc={tc} t={t}')
            # 更新温度和时间
            if t != self.tt:
                # 还没达到目标温度,每变化1度发送一次状态
                t += time_step
                delay = 4 - self.w
            else:
                # 已经达到目标温度处于保持状态,每秒发送一次状态
                delay = 1

            # 模拟时间变化
            tc += delay
            await asyncio.sleep(delay * self.ts)
예제 #8
0
    async def login(self, t_host: str, t_port: int, s_host: str, s_port: int,
                    k: str) -> bool:
        """
        房间登录到test和服务器的协程
        :param t_host: test的host
        :param t_port: test的端口
        :param s_host: 服务器的host
        :param s_port: 服务器的端口
        :param k: 验收分配的密钥
        :return: test和服务器均登录成功返回True
        """

        ev_loop = asyncio.get_event_loop()
        try:
            # 连接并登录test
            self.tr, self.tw = await asyncio.open_connection(t_host,
                                                             t_port,
                                                             loop=ev_loop)
            b4.send_line(self.tw, f'k={k} r={self.id}')
            rl = await b4.recv_line(self.tr, 'e')

            if len(rl) == 1 and rl[0] == '0':
                # test登录成功,连接并登录服务器
                log.info("Connected to the test program")
                self.sr, self.sw = await asyncio.open_connection(s_host,
                                                                 s_port,
                                                                 loop=ev_loop)
                b4.send_line(self.sw, f'r={self.id}')
                rl = await b4.recv_line(self.sr, 'e')
                if len(rl) == 1 and rl[0] == '0':  # 服务器登录成功
                    log.info("Connected to the server")
                    return True
        except ConnectionRefusedError as e:
            print(e)
        self.close()
        return False