def get_device_list(): ''' page: 当前页码 size: 每页读取数目, 最大不超过50项 city: 查询的城市 如不传或者为None则查询全部城市 area: 查询城市所属区域,如不传或者为None则查询该城市全部区域,前置条件必须有城市信息 start_time: 查询的起始时间段 时间段其实时间必须小于或者等于end_time end_time: 查询的结束时间段 时间段必须大于或者等于start_time state: 当前设备状态 如 为None 则查询所有状态 :return: ''' # 同步设备存活状态到mysql中 DeviceService.sync_device_alive_status() return DeviceService.search_list()
def to_dict(self): to_json = { 'id': self.id, 'user_id': self.user_id, 'device_id': self.device_id, 'province': self.province, 'city': self.city, 'area': self.area, 'location': self.location, 'cost_money': self.cost_money, 'ctime': self.ctime.strftime('%Y-%m-%d %H:%M:%S'), 'utime': self.utime.strftime('%Y-%m-%d %H:%M:%S'), 'end_time': self.end_time.strftime('%Y-%m-%d %H:%M:%S'), 'cost_time': self.cost_time # 分钟 } item = User.get(self.user_id) if item is not None: to_json['user'] = item.to_dict() item = DeviceService.get_device_by_id(self.device_id) if item is not None: to_json['device'] = item.to_dict() return to_json
def get_device_game_manage(): ''' page: 当前页码 size: 每页读取数目, 最大不超过50项 :return: ''' return DeviceService.search_list()
def get_device_by_id(device_id): device = None while True: try: # 先通过设备mac地址查找 device = DeviceService.get_device_by_code(device_id) if device is not None: break a_id = int(device_id) device = DeviceService.get_device_by_id(a_id) except Exception as e: log.error("设备信息无法转换为 int 类型: device_id = {}".format(device_id)) log.exception(e) break if device is None: return success(None) # 获取设备最新存活状态 device.alive = DeviceService.get_device_alive_status(device.device_code) return success(device.to_dict())
def keep_alive(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") record_key = request.json.get('token') if record_key is None: return fail(HTTP_OK, u"not have token!!!") device_code = request.json.get('device_code') if device_code is None: log.error( "无法保持心跳, 没有传入device_code: record_key = {}".format(record_key)) return fail(HTTP_OK, u"not have device_code!!!") # 保持心跳 DeviceService.keep_device_heart(device_code) charging = redis_cache_client.get(record_key) if charging is None: return success({ "status": 0, "msg": "keepalive failed!reason:token invalid" }) # 获得keep_alive_key 更新最新存活时间 user_online_key = RedisClient.get_user_online_key(record_key) # 设置最新存活时间 最多存在五分钟 redis_cache_client.setex(user_online_key, settings.MAX_LOST_HEART_TIME, int(time.time())) return success({ "status": 1, "msg": "keepalive success", "data": WindowsService.get_current_time_charging(charging) })
def get_device_game_state(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") device_code = request.json.get('device_code') if not isinstance(device_code, basestring): return fail(HTTP_OK, u"参数类型错误!") update_state = DeviceService.get_update_state(device_code) if update_state is None: log.error("当前设备号没有获取到任何设备信息: {}".format(device_code)) return fail(HTTP_OK, u'当前设备号信息不正确,无法获取更新状态信息') return success(update_state)
def delete_devices(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") id_list = request.json.get('list', None) if not isinstance(id_list, list): log.warn("参数错误: id_list = {}".format(id_list)) return fail(HTTP_OK, u"传入不是id列表") result_list = [] for device_id in id_list: if not DeviceService.delete_device(device_id): log.warn("当前设备删除失败: device_id = {}".format(device_id)) continue result_list.append(device_id) return success(result_list)
def device_game_list(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") device_code = request.json.get('device_code') device = DeviceService.get_device_by_code(device_code) if device is None: log.error("当前设备号没有获取到任何设备信息: {}".format(device_code)) return fail(HTTP_OK, u"参数错误!!") # if not isinstance(page, int) or \ # not isinstance(size, int): # log.error("获取游戏列表参数错误: page = {} size = {} device_code = {}".format( # page, size, device_code)) # return fail(HTTP_OK, u"参数错误!!") # # if page <= 0 or size <= 0: # log.error("获取游戏列表参数错误, 不能小于0: page = {} size = {} device_code = {}".format( # page, size, device_code)) # return fail(HTTP_OK, u"参数错误!!") return DeviceGameService.get_device_game_list(device.id)
def check_connect(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") device_code = request.json.get('device_code') if device_code is None: return fail(HTTP_OK, u"not have device_code!!!") # 获得设备使用状态 device_status = DeviceService.get_device_status(device_code) if device_status is None: return success({ 'status': -1, 'device_status': device_status, 'msg': "not deploy" }) # 保持心跳 DeviceService.keep_device_heart(device_code) # 从维护状态跳转到空闲状态 if device_status == DeviceStatus.STATUS_MAINTAIN: log.info("当前状态为维护状态,设备已经有心跳需要重新设置空闲状态!") DeviceService.status_transfer(device_code, device_status, DeviceStatus.STATUE_FREE) # 重新获得设备状态 device_status = DeviceService.get_device_status(device_code) device_code_key = RedisClient.get_device_code_key(device_code) record_key = redis_cache_client.get(device_code_key) if record_key is None: return success({ 'status': 0, 'device_status': device_status, 'msg': "not login" }) return success({ "status": 1, "token": record_key, 'device_status': device_status, "msg": "login successed!" })
def deploy_device(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") # json = { # 'province': 'xxx', # 'city': 'xxxx', # 'area': 'xxxx', # 'location': 'xxx', # 'device_code': 'xxxx', # } province = request.json.get('province', None) city = request.json.get('city', None) area = request.json.get('area', None) location = request.json.get('location', None) if province is None or city is None \ or area is None or location is None \ or province == '' or city == '' \ or area == '' or location == '': log.warn( "地址信息传入错误: province = {} city = {} area = {} location = {}".format( province, city, area, location)) return fail(HTTP_OK, u"地址信息传入错误!") # 获得设备编号信息 device_code = request.json.get('device_code', None) if device_code is None: log.warn("没有设备编号信息无法部署...") return fail(HTTP_OK, u"没有设备编号信息无法部署!") charge_id = request.json.get('charge_id', None) if charge_id is None: log.warn("当前部署没有传入费率模板ID: device_code = {}".format(device_code)) return fail(HTTP_OK, u"没有传入费率模板ID") charge = Charge.get(charge_id) if charge is None: log.warn("当前费率模板不存在: charge_id = {} device_code = {}".format( charge_id, device_code)) return fail(HTTP_OK, u"当前费率模板不存在!") # 先获得地址信息 通过地址四个属性进行查找 address = Address.find_address(province, city, area, location) if address is None: # 如果地址信息不存在则创建地址但是设备数要先初始化为0 address, is_success = Address.create(province, city, area, location, device_num=0) if address is None: log.warn( "部署设备时地址信息创建失败了: province = {} city = {} area = {} location = {} device_code = {}" .format(province, city, area, location, device_code)) return fail(HTTP_OK, u"新建地址信息失败了!") # 先判断设备是否已经存在设备列表中 device = DeviceService.get_device_by_code(device_code) if device is None: # 如果没有找到设备信息则新建设备信息 device, is_success = DeviceService.create(device_code, address.id, charge_id) if device is None: log.warn("新建设备信息失败了!!") return fail(HTTP_OK, u"新建设备信息失败了!") if not address.add_device_num(1): log.warn("新增设备数目存储失败!!") return fail(HTTP_OK, u"新增设备数目存储失败!") # 部署游戏信息 DeviceGameService.deploy_device_game(device) # 这里添加部署记录然后返回 deploy, is_success = Deploy.create(device.id, province, city, area, location) if deploy is None: log.warn("添加部署记录失败!") return fail(HTTP_OK, u"添加部署记录失败!") log.info( "添加部署记录成功: province = {} city = {} area = {} location = {} device_code = {}" .format(province, city, area, location, device_code)) return success(deploy.to_dict()) # 添加部署记录 先判断当前部署的位置是否和设备当前所处的位置是一样的 if device.address_id == address.id: log.info( "当前设备部署的位置没有发生任何变化,不需要记录: device.id = {} address.id = {}".format( device.id, address.id)) return success(u"当前设备部署位置没有发生任何变化,不需要增加部署记录") # 先获得之前部署的位置 address_old = Address.get(device.address_id) if address_old.device_num > 0: if not address_old.add_device_num(-1): return fail(HTTP_OK, u"减少设备数目存储失败!") # 然后更改部署的位置 device.address_id = address.id if not address.add_device_num(1): log.warn("新增设备数目存储失败!!") return fail(HTTP_OK, u"新增设备数目存储失败!") # 增加部署记录 deploy, is_success = Deploy.create(device.id, province, city, area, location) if deploy is None: log.warn("添加部署记录失败!") return fail(HTTP_OK, u"添加部署记录失败!") log.info( "添加部署记录成功: province = {} city = {} area = {} location = {} device_code = {}" .format(province, city, area, location, device_code)) return success(deploy.to_dict())
def modify_device_game_state(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") device_code = request.json.get('device_code') update_state = request.json.get('update_state') if update_state not in (DeviceUpdateStatus.UPDATE_ING, DeviceUpdateStatus.UPDATE_FINISH): log.error("当前状态不允许: update_state = {}".format(update_state)) return fail(HTTP_OK, u"参数错误!") device = DeviceService.get_device_by_code(device_code) if device is None: log.error("当前设备号没有获取到任何设备信息: {}".format(device_code)) return fail(HTTP_OK, u"参数错误,获取设备信息失败!!") # 获取当前游戏更新状态 current_update_state = DeviceService.get_update_state(device) # 获取当前设备状态 current_status = DeviceService.get_device_status(device) # 如果当前发送过来的状态是ing 则设备当前游戏更新状态必须是ing,否则状态错误 if update_state == DeviceUpdateStatus.UPDATE_ING: if current_update_state == DeviceUpdateStatus.UPDATE_CHECK: return fail(HTTP_OK, u"当前游戏更新状态错误, 自检中不接收ing状态") # 锁定设备 if current_status != DeviceStatus.STATUE_FREE and \ current_status != DeviceStatus.STATUE_LOCK: return fail(HTTP_OK, u"当前设备不为空闲或者锁定状态,无法更新!") # 如果当前设备为空闲状态 则锁定设备 if current_status == DeviceStatus.STATUE_FREE: if not DeviceService.set_device_status(device, DeviceStatus.STATUE_LOCK): log.error("锁定设备失败,设置设备状态信息失败: device_id = {}".format( device.id)) return fail(HTTP_OK, u'锁定设备失败,设置设备状态信息失败!!') if DeviceService.set_update_state(device, update_state): return success(u"设备游戏更新状态设置成功!") return fail(HTTP_OK, u"更新状态设置失败") # 判断当前属于什么状态 if current_update_state == DeviceUpdateStatus.UPDATE_FINISH: return success(u'当前属于游戏更新完成状态,不需要设置') # 如果当前设备被锁定了 则解锁 if current_status == DeviceStatus.STATUE_LOCK: if not DeviceService.set_device_status(device, DeviceStatus.STATUE_FREE): log.error("解锁设备异常: device_id = {}".format(device.id)) return fail(HTTP_OK, u'设备解锁失败,多进程写入设备状态异常!') # 如果当前属于更新中状态 if current_update_state == DeviceUpdateStatus.UPDATE_ING: # 设置游戏更新完成。。 DeviceGameService.update_device_game(device_id=device.id) if DeviceService.set_update_state(device, update_state, last_update_time=datetime.now()): return success(u"设备游戏更新状态设置成功!") return fail(HTTP_OK, u"更新状态设置失败") if DeviceService.set_update_state(device, update_state): return success(u"设备游戏更新状态设置成功!") return fail(HTTP_OK, u"更新状态设置失败")
def qr_code_online(device_code): # # 当前用户没有登录 # LOGIN_ERROR_BIND = -1 # # 当前用户已经被删除 # LOGIN_ERROR_DELETE = -2 # # 当前用户被禁止使用 # LOGIN_ERROR_FORBID = -3 # # 当前设备不存在 # LOGIN_ERROR_NOT_FIND = -4 # # 用户余额不足 # LOGIN_ERROR_NOT_SUFFICIENT_FUNDS = -5 # # 上机失败 未知错误 # LOGIN_ERROR_UNKNOW = -6 # # 设备已经在使用了 # LOGIN_ERROR_DEVICE_IN_USEING = -7 # # 当前用户已经在使用上机了,但是不是当前设备在使用 # LOGIN_ERROR_USER_IN_USEING = -8 # # 当前设备不处于空闲状态,不能上机 # LOGIN_ERROR_DEVICE_NOT_FREE = -9 scan_from = request.args.get('from') # 登录链接 login_url = url_for("wechat.menu", name="login") # 通过微信二维码扫描则需要判断当前用户是否已经关注公众号 if scan_from != 'playing': # # 初始化用户关注信息 # subscribe, nick_name, head_img_url = 0, '', '' openid = session.get('openid', None) # 如果不是微信二维码扫描 则跳转到登录界面 if openid is None: log.info("当前扫描登录没有openid,需要跳转到登录界面..") return redirect(login_url) # 获得用户的关注状态 以及头像和昵称信息 subscribe, nick_name, head_img_url = get_wechat_user_info(openid) # 如果用户没有关注微信号 直接跳转到关注页面 if subscribe != 1: log.info("当前用户没有关注公众号: subscribe = {} openid = {}".format( subscribe, openid)) return redirect(ATTENTION_URL) # 如果当前用户已经关注 则直接跳转到 祥基指定的链接 2017-10-13 15:26:00 url = '#/playing?code={}'.format(device_code) log.info("当前用户已经关注了公众号,跳转链接: {}".format(url)) return redirect(url) user_id_cookie = session.get('u_id') if user_id_cookie is None: log.warn("当前session中没有u_id 信息,需要登录...") return fail(HTTP_OK, u'当前用户没有登录', LOGIN_ERROR_BIND) user_id = decode_user_id(user_id_cookie) if user_id is None: log.warn( "当前用户信息被篡改,需要重新登录: user_id_cookie = {}".format(user_id_cookie)) return fail(HTTP_OK, u'当前用户登录信息被篡改, 不能登录', LOGIN_ERROR_BIND) # 获得用户信息 user = get_current_user(user_id) if user is None: log.warn("当前user_id还未绑定手机号码: user_id = {}".format(user_id)) return fail(HTTP_OK, u"用户还绑定手机号码登录!", LOGIN_ERROR_BIND) # 如果当前用户 被禁用 则不能上机 if user.deleted: log.warn("当前用户已经被删除了,无法上机: user_id = {}".format(user.id)) return fail(HTTP_OK, u"当前用户已经被删除了,不能上机", LOGIN_ERROR_DELETE) # 判断当前用户是否已经被禁用了 if user.state == 'unused': log.warn("当前用户已经被禁用了,无法上机: user_id = {}".format(user.id)) return fail(HTTP_OK, u"当前用户已经被禁用了,不能上机", LOGIN_ERROR_FORBID) # 获得设备信息 device = DeviceService.get_device_by_code(device_code=device_code) if device is None: log.warn("当前设备号没有对应的设备信息: device_code = {}".format(device_code)) return fail(HTTP_OK, u"设备信息异常,设备不存在", LOGIN_ERROR_NOT_FIND) # 获得最新费率 charge_mode = DeviceService.get_charge_mode(device) log.info("当前费率: charge_mode = {}".format(charge_mode)) # 判断用户是否余额充足 如果小于一分钟不能上机 if user.balance_account < charge_mode: log.info( "用户余额不足,不能上机: user_id = {} device_id = {} account = {}".format( user.id, device.id, user.balance_account)) return fail(HTTP_OK, u"用户余额不足,不能上机!", LOGIN_ERROR_NOT_SUFFICIENT_FUNDS) # 判断是否已经在redis中进行记录 record_key = RedisClient.get_record_key(user.id, device.id) # 获得用户上机key user_key = RedisClient.get_user_key(user.id) # 获得设备上机key device_key = RedisClient.get_device_key(device.id) # 判断是否已经登录了 charging = redis_cache_client.get(record_key) if charging is None: # 判断当前设备是否已经在使用了 if redis_cache_client.get(device_key): log.warn("当前设备{}已经在被使用,但是用户ID = {}又在申请".format(device.id, user.id)) return fail(HTTP_OK, u"当前设备已经在使用上机了,但是不是当前用户在使用!", LOGIN_ERROR_DEVICE_IN_USING) # 判断当前用户是否已经上机了 if redis_cache_client.get(user_key): log.warn("当前用户{}已经在上机,但是又在申请当前设备ID = {}".format( user.id, device.id)) return fail(HTTP_OK, u"当前用户已经在使用上机了,但是不是当前设备在使用!", LOGIN_ERROR_USER_IN_USING) # 判断当前设备是否处于空闲状态 且设备必须处于在线状态 device_status = DeviceService.get_device_status(device) device_alive = DeviceService.get_device_alive_status(device) if device_status != DeviceStatus.STATUE_FREE or device_alive != Device.ALIVE_ONLINE: log.warn("当前设备不处于空闲状态,不能上机: device_id = {} state = {} alive = {}". format(device.id, device_status, device_alive)) return fail(HTTP_OK, u"当前设备不处于空闲状态,或者当前设备不在线,不能上机!", LOGIN_ERROR_DEVICE_NOT_FREE) # 判断当前设备是否正在更新 或者正在自检,这种状态下不能够登录上机 current_update_state = DeviceService.get_update_state(device) if current_update_state == DeviceUpdateStatus.UPDATE_ING or \ current_update_state == DeviceUpdateStatus.UPDATE_CHECK: log.info( "当前设备正在更新或者自检中,不能登录: device_id = {} current_update_state = {}". format(device.id, current_update_state)) return fail(HTTP_OK, u"当前设备处于自检或者更新中,不能上机!", LOGIN_ERROR_DEVICE_NOT_FREE) log.info("用户还未上机可以进行上机: user_id = {} device_id = {}".format( user.id, device.id)) if not WindowsService.do_online(user, device, charge_mode): log.warn("上机记录创建失败,上机失败: user_id = {} device_id = {}".format( user.id, device.id)) return fail(HTTP_OK, u"上机异常!!", LOGIN_ERROR_UNKNOW) log.info("来自微信端游戏仓界面扫描: user_id = {} device_id = {}".format( user.id, device.id)) return success()
def maintain_login(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") device_code = request.json.get('device_code') username = request.json.get('username') password = request.json.get('password') if device_code is None or username is None or password is None: log.error( "参数错误,无法登录维修账号: device_code = {} username = {} password = {}". format(device_code, username, password)) return fail(HTTP_OK, u"参数错误!!") # 判断维修人员用户密码是否正确 maintain = MaintainService.get_maintain_by_username(username) if maintain is None: log.error("当前维修人员账号不存在: username = {} password = {}".format( username, password)) return fail(HTTP_OK, u"当前维修人员账号不存在,维修人员无法登录!!") # 判断当前用户是否已经被禁用了 if maintain.state == Maintain.STATUS_FORBID: return fail(HTTP_OK, u"当前账户已被禁用,无法登录!!") # 判断密码是否正确 if not maintain.verify_password(password): log.error("当前维护人员密码错误: username = {} password = {}".format( username, password)) return fail(HTTP_OK, u"密码错误,维修人员无法登录!!") # 判断当前设备信息是否存在 device = DeviceService.get_device_by_code(device_code) if device is None: log.error("当前设备号没有设备信息: device_code = {}".format(device_code)) return fail(HTTP_OK, u"当前设备号没有设备信息!!") # 判断当前设备存活状态 if DeviceService.get_device_alive_status(device) == Device.ALIVE_OFFLINE: log.error("当前设备离线,维修人员无法登录: device_code = {}".format(device_code)) return fail(HTTP_OK, u"当前设备离线,维修人员无法登录!!") # 判断当前设备使用状态 if DeviceService.get_device_status(device) == DeviceStatus.STATUE_BUSY: log.error("当前设备用户正在使用,维修人员无法登录: device_code = {}".format(device_code)) return fail(HTTP_OK, u"当前设备用户正在使用,维修人员无法登录!!") # 判断当前维护人员账号能否登录当前地址 if maintain.address_id != Maintain.ALL_ADDRESS_ID: address = Address.get(maintain.address_id) if address is None: log.error("当前维护人员管理的地址信息不存在,无法登录") return fail(HTTP_OK, u"当前维护人员管理的地址信息不存在,无法登录!") device_address = device.address.get_full_address() maintain_address = address.get_full_address() if device_address != maintain_address: log.error( "当前维护人员管理的地址与设备所在地址不一致,无法登录: maintain_id = {} device_id = {}" " device_address = {} maintain_address = {}".format( maintain.id, device.id, device_address, maintain_address)) return fail(HTTP_OK, u"当前维护人员管理的地址与设备所在地址不一致,无法登录!") # 开始登录,先设置设备状态 if not DeviceService.set_device_status(device, DeviceStatus.STATUS_MAINTAIN): log.error( "设备状态切换错误, 维修人员无法登录: device_code = {} username = {} password = {}". format(device_code, username, password)) return fail(HTTP_OK, u"设备状态切换异常, 维修人员无法登录!") log.info("维修人员登录设备成功: device_code = {} username = {} password = {}".format( device_code, username, password)) return success(u"登录成功")
def lock_device(): if not request.is_json: log.warn("参数错误...") return fail(HTTP_OK, u"need application/json!!") device_id = request.json.get('id') lock = request.json.get('lock') if device_id is None or lock is None: log.error("传入参数不正确: id = {} lock = {}".format(device_id, lock)) return fail(HTTP_OK, u"传入参数错误!") # 获得设备信息 device = DeviceService.get_device_by_id(device_id) if device is None: log.error("当前设备ID没有找到设备信息: device_id = {}".format(device_id)) return fail(HTTP_OK, u"当前设备ID没有找到设备信息!") # 获取当前设备存活状态 alive = DeviceService.get_device_alive_status(device) if alive == Device.ALIVE_OFFLINE: log.info("当前设备不在线,无法锁定设备: device_id = {} alive = {}".format( device_id, alive)) return fail(HTTP_OK, u"当前设备不在线,无法锁定设备!") # 获取设备当前使用状态 use_status = DeviceService.get_device_status(device) if use_status is None: log.error("获取当前设备状态错误, 无法操作设备: device_id = {}".format(device_id)) return fail(HTTP_OK, u'获取当前设备状态错误, 无法操作设备') # 当前是否是想解锁设备 if not lock: if use_status == DeviceStatus.STATUE_LOCK: if not DeviceService.set_device_status(device, DeviceStatus.STATUE_FREE): return fail(HTTP_OK, u'设备解锁失败,多进程写入设备状态异常!') log.info("解锁设备成功: device_id = {} device_code = {}".format( device.id, device.device_code)) return success(u'解锁设备成功') return success(u'当前设备未锁定,不需要解锁!') # 判断设备是否处于维护状态 if use_status == DeviceStatus.STATUS_MAINTAIN: log.info("当前设备维护人员已登录,无法锁定设备: device_id = {} use_status = {}".format( device_id, use_status)) return fail(HTTP_OK, u"当前设备维护人员已登录,无法锁定设备!") if use_status == DeviceStatus.STATUE_LOCK: log.info("当前设备已被锁定,不需要再锁定: device_id = {} use_status = {}".format( device_id, use_status)) return success(u"当前设备已被锁定,不需要再锁定") # 当前设备处于忙碌状态,锁定设备 if use_status == DeviceStatus.STATUE_BUSY: # log.info("当前设备有用户在使用,强制用户下机,锁定设备: device_id = {} use_status = {}".format(device_id, use_status)) # if not WindowsService.do_offline_order_by_device_code(device.device_code): # return fail(HTTP_OK, u"强制用户下机失败,无法锁定设备!") # # if not DeviceService.set_device_status(device, DeviceStatus.STATUE_LOCK): # log.error("锁定设备失败,设置设备状态信息失败: device_id = {}".format(device_id)) # return fail(HTTP_OK, u'锁定设备失败,设置设备状态信息失败!!') # log.info("锁定设备成功: device_id = {} device_code = {}".format(device.id, device.device_code)) # return success(u'当前设备有用户在使用,强制用户下机,锁定设备成功') return fail(HTTP_OK, u"当前设备用户正在使用,不能锁定!") if not DeviceService.set_device_status(device, DeviceStatus.STATUE_LOCK): log.error("锁定设备失败,设置设备状态信息失败: device_id = {}".format(device_id)) return fail(HTTP_OK, u'锁定设备失败,设置设备状态信息失败!!') log.info("锁定设备成功: device_id = {} device_code = {}".format( device.id, device.device_code)) return success(u'锁定设备成功')
def cal_offline(user_id, device_id, record_id, charge_mode): try: # 获得用户信息 user = User.get(user_id) # 获得设备信息 device = DeviceService.get_device_by_id(device_id) # 获得试用记录 record = UseRecord.get(record_id) # 记录下机时间 record.end_time = datetime.now() # 设置设备自检, 如果设备处于完成更新状态 则可以进入自检,否则其他状态不能设置自检 if DeviceService.get_update_state( device) == DeviceUpdateStatus.UPDATE_FINISH: if not DeviceService.set_update_state( device, DeviceUpdateStatus.UPDATE_CHECK): log.error("设置自检状态失败: device_code = {}".format( device.device_code)) return False, None, None log.info("设置自检状态成功: device_code = {}".format( device.device_code)) # 如果自检状态设备成功,则直接锁定设备 if not DeviceService.set_device_status( device, DeviceStatus.STATUE_LOCK): log.error("设备自检状态设置成功,锁定设备失败: device_id = {}".format( device.id)) return False, None, None log.info("设备自检状态设置成功,锁定设备成功: device_id = {}".format( device.id)) else: # 设置设备为空闲状态 if not DeviceService.set_device_status( device, DeviceStatus.STATUE_FREE): log.error("设置设备状态异常,下机失败!") return False, None, None log.info("本次上机时间: {} 下机时间: {} 使用记录ID: {} 当前设备: {}".format( record.ctime.strftime('%Y-%m-%d %H:%M:%S'), record.end_time.strftime('%Y-%m-%d %H:%M:%S'), record_id, device.device_code)) # 计算花费时间 seconds = (record.end_time - record.ctime).seconds # # 如果大于半分钟就以一分钟的价格扣钱 # if 30 <= seconds < 60: # seconds = 60 # 计算下机时长 record.cost_time = cal_cost_time(seconds) log.info( "本次上机花费的时间: user_id = {} device_id = {} cost_time = {}".format( user_id, device_id, record.cost_time)) # 计算花费金钱 record.cost_money = record.cost_time * charge_mode log.info("本次上机花费的金钱: user_id = {} device_id = {} cost_money = {}". format(user_id, device_id, record.cost_money)) # 计算设备获得的金钱数目 device.income += record.cost_money # 计算用户花费的钱 user.balance_account -= record.cost_money if user.balance_account < 0: user.balance_account = 0 log.info("上机后用户所剩余额: user_id = {} balance_account = {}".format( user_id, user.balance_account)) user.used_account += record.cost_money user.total_cost_time += record.cost_time # 更新各属性时间 user.utime = datetime.now() device.utime = datetime.now() record.utime = datetime.now() log.info("当前用户总的上机时长: user_id = {} total_cost_time = {}".format( user_id, user.total_cost_time)) db.session.add(user) db.session.add(device) db.session.add(record) db.session.commit() return True, record, user except Exception as e: log.error( "未知错误: user_id = {} device_id = {} record_id = {}".format( user_id, device_id, record_id)) log.exception(e) db.session.rollback() return False, None, None
def do_online(user, device, charge_mode): log.info("用户还未上机可以进行上机: user_id = {} device_id = {}".format( user.id, device.id)) record, is_success = UseRecord.create(user.id, device.id, device.address.province, device.address.city, device.address.area, device.address.location) if not is_success: return False # 判断是否已经在redis中进行记录 record_key = RedisClient.get_record_key(user.id, device.id) # 获得用户上线key user_key = RedisClient.get_user_key(user.id) # 获得设备上线key device_key = RedisClient.get_device_key(device.id) # 获得当前设备token device_code_key = RedisClient.get_device_code_key(device.device_code) # 获得keep_alive_key 更新最新存活时间 user_online_key = RedisClient.get_user_online_key(record_key) log.info( "当前上机时间: user_id:{} device_id:{} record_id:{} ctime:{}".format( user.id, device.id, record.id, record.ctime.strftime('%Y-%m-%d %H:%M:%S'))) # 获得计费结构体 charging = record.to_charging() # 得到计费方式 charging['charge_mode'] = charge_mode # 得到当前用户总额 charging['balance_account'] = user.balance_account # 填充设备机器码 charging['device_code'] = device.device_code # 填充用户的openid charging['openid'] = user.openid # charging = { # 'id': self.id, # 'user_id': self.user_id, # 'device_id': self.device_id, # # 花费金额数目 # 'cost_money': self.cost_money, # # 上机时间 # 'ctime': self.ctime.strftime('%Y-%m-%d %H:%M:%S'), # # 更新时间,主要用户同步计费 # 'utime': self.utime.strftime('%Y-%m-%d %H:%M:%S'), # # 已经上机时间 # 'cost_time': self.cost_time, # # 计费方式 目前默认 5分钱/分钟 # 'charge_mode': 5, # # 当前用户余额 # 'balance_account': 10000, # # 设备机器码 # 'device_code': 'xx-xx-xx-xx-xx-xx', # } charge_str = json.dumps(charging) # 操作redis 需要加锁 lock = DistributeLock(user_key, redis_cache_client) try: lock.acquire() # 设置设备当前使用状态 if not DeviceService.set_device_status(device, DeviceStatus.STATUE_BUSY): log.error("设置设备状态失败, 上机异常!!!") return False # 开始上线 把上线信息存储redis redis_cache_client.set(record_key, charge_str) redis_cache_client.set(user_key, record_key) redis_cache_client.set(device_key, record_key) # 根据设备机器码获得记录token redis_cache_client.set(device_code_key, record_key) # 设置最新存活时间 最多存活五分钟 import time redis_cache_client.setex(user_online_key, settings.MAX_LOST_HEART_TIME, int(time.time())) is_success = True except Exception as e: is_success = False log.exception(e) finally: lock.release() # 判断上线是否成功 if is_success: # 发送上线通知 TemplateService.online(user.openid, record.ctime, device.address, user.balance_account, charge_mode) return True