Przeglądaj źródła

新增鼎芯电信达量断网、接入号码查询

zhangdongming 1 rok temu
rodzic
commit
0590c40d8a

+ 18 - 0
Controller/UnicomCombo/UnicomComboController.py

@@ -403,6 +403,9 @@ class UnicomComboView(View):
             elif cls.is_telecom_sim(iccid):  # 鼎芯电信
                 params['card_type'] = 3
                 params['status'] = 2
+                access_number = cls.get_access_number(iccid)
+                if access_number:
+                    params['access_number'] = access_number
                 UnicomDeviceInfo.objects.create(**params)
                 return response.json(0)
             elif cls.is_dingxin_iot(iccid):  # 鼎芯物联卡
@@ -423,6 +426,21 @@ class UnicomComboView(View):
                         .format(serial_no, e.__traceback__.tb_lineno, repr(e)))
             return response.json(177, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
+    @classmethod
+    def get_access_number(cls, iccid):
+        """
+        根据19位数ICCID查询接入号码
+        @param iccid: 20位ICCID
+        @return: 11位接入号码
+        """
+        telecom = TelecomObject()
+        result = telecom.get_telephone(iccid[0:19])
+        if not result:
+            return None
+        if result['RESULT'] == '0':
+            return result['SMSG']
+        return None
+
     @classmethod
     def is_telecom_sim(cls, iccid):
         """

+ 2 - 1
Model/models.py

@@ -3295,11 +3295,12 @@ class UnicomDeviceInfo(models.Model):
     status = models.SmallIntegerField(default=0, verbose_name=u'状态{0:可测试,1:测试完成,2:已使用}')
     serial_no = models.CharField(default='', db_index=True, max_length=32, verbose_name=u'设备序列号')
     user_id = models.CharField(blank=True, max_length=32, verbose_name=u'用户id')
-    card_type = models.SmallIntegerField(default=0, verbose_name=u'状态{0:联通,1:电信,2:移动,4:其它,5:国际}')
+    card_type = models.SmallIntegerField(default=0, verbose_name=u'状态{0:联通,1:五兴电信,2:移动,3:鼎芯电信,4:其它,5:鼎芯国际}')
     main_card = models.SmallIntegerField(default=0, verbose_name=u'SIM卡类型{0:拔插卡,1:贴片卡}')
     sim_used_flow = models.DecimalField(default=0, max_digits=10, decimal_places=2, verbose_name=u'sim卡已用总流量(MB)')
     sim_cycle_used_flow = models.DecimalField(default=0, max_digits=10, decimal_places=2,
                                               verbose_name=u'设备账期已用流量(MB)')
+    access_number = models.CharField(blank=True, max_length=32, verbose_name=u'接入号码')
     updated_time = models.IntegerField(default=0, verbose_name='更新时间')
     created_time = models.IntegerField(default=0, verbose_name='创建时间')
 

+ 47 - 0
Object/TelecomObject.py

@@ -424,3 +424,50 @@ class TelecomObject:
                         .format(e.__traceback__.tb_lineno, repr(e)))
             return None
 
+    def off_net_action_by_access_number(self, access_number, action, quota, a_type):
+        """
+        表示达量断网新增、修改及取消接口
+        :param access_number: 接入号码access_number。
+        :param action: action=1,表示新增达量断网阈值;action=2,表示修改达量断网阈值;action=3,表示取消达量断网功能。
+                注:已达量断网的物联网卡无法通过取消达量断网功能实现恢复上网。
+        :param quota: 要添加或调整的断网阈值(单位:M)比如 1024,注意:1)设为-1表示无限制2)设为0表示有上网流量产生就会立即断网3)只能设置为-1,0或正整数
+        :param a_type: type表示要添加或调整的断网类型:设置为1:表示用户总使用量 设置为2:表示超出套餐外使用量
+        :return: 修改结果
+        :raises ValueError: 如果响应为空或HTTP请求失败。
+        """
+        try:
+            if not access_number:
+                raise ValueError("*****TelecomObject.off_net_action_by_access_number error****access_number不能为空")
+            method = 'offNetAction'
+            arr = [method, self.user_id, access_number, self.password, action, quota, a_type]
+            re_params = self.get_params_dict_by_access_number(method, access_number, arr)
+            re_params['action'] = action
+            re_params['quota'] = quota
+            re_params['type'] = a_type
+            response = self.session.post(self.url, data=re_params)
+
+            if response.status_code != 200:
+                LOGGER.info(
+                    f"*****TelecomObject.off_net_action_by_access_number error HTTP请求失败,状态码: {response.status_code}")
+                return None
+
+            msg = response.text
+            if not msg:
+                return None
+
+            content_type = response.headers.get('Content-Type', '')
+            if 'application/xml' in content_type or 'text/xml' in content_type:
+                result = xmltodict.parse(msg)
+            elif 'application/json' in content_type or 'text/json' in content_type:
+                result = json.loads(msg)
+                LOGGER.info(f"***TelecomObject.off_net_action_by_access_number 查询产品资料异常:{access_number},error{result}")
+                return None
+            else:
+                LOGGER.info("***TelecomObject.off_net_action_by_access_number 无法识别的响应类型: {}".format(content_type))
+                return None
+            return result
+
+        except Exception as e:
+            LOGGER.info('***TelecomObject.off_net_action_by_access_number:errLine:{}, errMsg:{}'
+                        .format(e.__traceback__.tb_lineno, repr(e)))
+            return None

+ 70 - 0
Service/TelecomService.py

@@ -0,0 +1,70 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : TelecomService.py
+@Time    : 2024/1/24 15:12
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+import time
+from decimal import Decimal
+from Ansjer.config import LOGGER
+from Model.models import UnicomDeviceInfo
+from Object.RedisObject import RedisObject
+from Object.TelecomObject import TelecomObject
+
+
+class TelecomService:
+
+    @classmethod
+    def query_total_usage_by_access_number(cls, iccid, access_number, key, expire=600):
+        """
+        根据接入号码查询设备总流量使用量(实现缓存)
+        @param iccid: 20位ICCID
+        @param key: 缓存key
+        @param expire: 失效时间
+        @param access_number: 接入号码
+        @return: 查询流量结果
+        """
+        redis = RedisObject()
+        sim_flow_used_total = redis.get_data(key)
+        if sim_flow_used_total:
+            return Decimal(sim_flow_used_total).quantize(Decimal('0.00'))
+        else:
+            # 查询SIM卡信息
+            sim_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
+            if not sim_qs:
+                return None
+            sim_vo = sim_qs.first()
+
+            telecom = TelecomObject()
+            data = telecom.query_total_usage_by_date(access_number)
+            if data and data['SvcCont']['resultCode'] == '0' and 'dataCumulationTotal' in data['SvcCont']['result']:
+                cycle_total = data['SvcCont']['result'].get('dataCumulationTotal')
+            else:
+                LOGGER.info(f'query_total_usage_by_access_number查询流量异常,iccid:{iccid}')
+                return sim_vo.sim_used_flow + sim_vo.sim_cycle_used_flow
+
+            cycle_total = Decimal(cycle_total).quantize(Decimal('0.00'))
+
+            n_time = int(time.time())
+
+            # 判断数据库周期流量用量 是否大于API查询出来的周期用量 如果是则判定进入了下一个周期
+            if sim_vo.sim_cycle_used_flow != 0 and sim_vo.sim_cycle_used_flow > cycle_total:
+                sim_used_flow = sim_vo.sim_used_flow + sim_vo.sim_cycle_used_flow
+                sim_qs.update(
+                    sim_used_flow=sim_used_flow,
+                    sim_cycle_used_flow=cycle_total,
+                    updated_time=n_time
+                )
+                # 队列用量历史总量 + 上一个周期流量 + 当前周期流量 = 总消耗流量
+                sim_flow_used_total = sim_used_flow + cycle_total
+            elif cycle_total > sim_vo.sim_cycle_used_flow:  # API周期用量大于当前数据库用量则更新记录
+                sim_qs.update(sim_cycle_used_flow=cycle_total, updated_time=n_time)
+                # 队列用量历史总量 + 当前周期流量 = 总消耗流量
+                sim_flow_used_total = sim_vo.sim_used_flow + cycle_total
+            else:
+                sim_flow_used_total = sim_vo.sim_used_flow + sim_vo.sim_cycle_used_flow
+            redis.CONN.setnx(key, str(sim_flow_used_total))
+            redis.CONN.expire(key, expire)
+        return sim_flow_used_total