--- /dev/null
+# -*-coding:utf-8-*-
+
+#===============================================================================
+# 目录对比工具(包含子目录 ),并列出
+# 1、A比B多了哪些文件
+# 2、B比A多了哪些文件
+# 3、二者相同的文件: md5比较
+#===============================================================================
+
+import os
+import sys
+import time
+import difflib
+import hashlib
+import struct
+import shutil
+
+
+def getFileMd5(filename):
+ if not os.path.isfile(filename):
+ print('file not exist: ' + filename)
+ return
+ myhash = hashlib.md5()
+ f = open(filename,'rb')
+ while True:
+ b = f.read(8096)
+ if not b :
+ break
+ myhash.update(b)
+ f.close()
+ return myhash.hexdigest()
+
+
+def getAllFiles(path):
+ flist=[]
+ for root, dirs , fs in os.walk(path):
+ for f in fs:
+ f_fullpath = os.path.join(root, f)
+ f_relativepath = f_fullpath[len(path):]
+ flist.append(f_relativepath)
+ return flist
+
+
+def create_dirs(dir_path):
+ # print(dir_path)
+ if not os.path.exists(dir_path):
+ try:
+ os.makedirs(dir_path)
+ except OSError as exc: # Guard against race condition
+ if exc.errno != errno.EEXIST:
+ raise
+# 获取文件大小
+def get_FileSize(filePath):
+ fsize = os.path.getsize(filePath)
+ return fsize
+
+target_tmp_dir=""
+filelist=[]
+target_filelist_name=""
+
+if __name__ == '__main__':
+ target_tmp_dir = sys.argv[1]+"/fs"
+ target_filelist_name=target_tmp_dir+"/user/fileschecksum.txt"
+ if os.path.exists(target_filelist_name):
+ os.remove(target_filelist_name)
+ filelist=getAllFiles(target_tmp_dir)
+ create_dirs(target_tmp_dir+"/user/")
+ with open(target_filelist_name, 'w') as file:
+ for f in filelist:
+ fullpath=target_tmp_dir+f
+ print(fullpath)
+ fmd5=getFileMd5(fullpath)
+ fsize=get_FileSize(fullpath)
+ content = "{},{},{}\n".format(f,fsize,fmd5)
+ file.write(content)
+ file.close
+
+
+
+
--- /dev/null
+this is test3 file
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) xxxxxxxx Technologies Co., Ltd. 2021-2021. All rights reserved.
+* Description: language
+* Author: Graphic develop team
+* Create: 2021-07-06
+*/
+
+#ifndef UI_RESOURCE_STRING_H
+#define UI_RESOURCE_STRING_H
+#include <cstdint>
+namespace OHOS {
+enum UIResourceTextId : uint16_t {
+ STR_EXERCISE_OUTDOORWALKING = 0,\r
+ STR_EXERCISE_OUTDOORRUNNING = 1,\r
+ STR_EXERCISE_OUTDOORBIKING = 2,\r
+ STR_EXERCISE_GENERAL = 3,\r
+ STR_EXERCISE_FREETRAINING = 4,\r
+ STR_EXERCISE_RESISTANCETRAINING = 5,\r
+ STR_EXERCISE_SPINBIKE = 6,\r
+ STR_EXERCISE_TREADMILL = 7,\r
+ STR_EXERCISE_STROLLMACHINE = 8,\r
+ STR_EXERCISE_HIIT = 9,\r
+ STR_EXERCISE_CROSSFIT = 10,\r
+ STR_EXERCISE_GROUPCALISTHENICS = 11,\r
+ STR_EXERCISE_YOGA = 12,\r
+ STR_EXERCISE_YOGACAT = 13,\r
+ STR_EXERCISE_YOGACOW = 14,\r
+ STR_EXERCISE_YOGACOBRA = 15,\r
+ STR_EXERCISE_YOGAHERO1 = 16,\r
+ STR_EXERCISE_YOGAHERO2 = 17,\r
+ STR_EXERCISE_YOGAHERO3 = 18,\r
+ STR_EXERCISE_YOGAROLLING = 19,\r
+ STR_EXERCISE_INDOORWALKING = 20,\r
+ STR_EXERCISE_INDOORRUNNING = 21,\r
+ STR_EXERCISE_JUMPINGROPE = 22,\r
+ STR_EXERCISE_PILATES = 23,\r
+ STR_EXERCISE_CROSS_FIT = 24,\r
+ STR_EXERCISE_FUNCTIONALTRAINING = 25,\r
+ STR_EXERCISE_PHYSICALTRAINING = 26,\r
+ STR_EXERCISE_TAEKWONDO = 27,\r
+ STR_EXERCISE_BOXING = 28,\r
+ STR_EXERCISE_KICKBOXING = 29,\r
+ STR_EXERCISE_KARATE = 30,\r
+ STR_EXERCISE_FENCING = 31,\r
+ STR_EXERCISE_CORETRAINING = 32,\r
+ STR_EXERCISE_BODYCOMBAT = 33,\r
+ STR_EXERCISE_KENDO = 34,\r
+ STR_EXERCISE_HORIZONTALBAR = 35,\r
+ STR_EXERCISE_PARALLELBARS = 36,\r
+ STR_EXERCISE_CIRCUIT = 37,\r
+ STR_EXERCISE_AEROBICS = 38,\r
+ STR_EXERCISE_CALISTHENICE = 39,\r
+ STR_EXERCISE_P90X = 40,\r
+ STR_EXERCISE_KETTLEBELLTRAINING = 41,\r
+ STR_EXERCISE_MIXEDMARTIALARTS = 42,\r
+ STR_EXERCISE_STAIRCLIMBINGMACHINE = 43,\r
+ STR_EXERCISE_WEIGHTLIFTING = 44,\r
+ STR_EXERCISE_BARRE = 45,\r
+ STR_EXERCISE_HANDCYCLING = 46,\r
+ STR_EXERCISE_TRACKFIELD = 47,\r
+ STR_EXERCISE_WRESTLING = 48,\r
+ STR_EXERCISE_MINDBODY = 49,\r
+ STR_EXERCISE_FLEXIBILITY = 50,\r
+ STR_EXERCISE_MIXEDCARDIO = 51,\r
+ STR_EXERCISE_TRADITIONALSTRENGTHTRAINING = 52,\r
+ STR_EXERCISE_CROSSTRAINING = 53,\r
+ STR_EXERCISE_GYMNASTICS = 54,\r
+ STR_EXERCISE_STEPTRAINING = 55,\r
+ STR_EXERCISE_ELLIPTICALTRAINER = 56,\r
+ STR_EXERCISE_ROWINGMACHINE = 57,\r
+ STR_DANCING_GENERAL = 58,\r
+ STR_DANCING_BELLY = 59,\r
+ STR_DANCING_JAZZ = 60,\r
+ STR_DANCING_LATIN = 61,\r
+ STR_DANCING_BALLET = 62,\r
+ STR_DANCING_STREET = 63,\r
+ STR_DANCING_PUBLICSQUARE = 64,\r
+ STR_DANCING_ZUMBA = 65,\r
+ STR_DANCING_SOCIALDANCE = 66,\r
+ STR_DANCING_TAPDANCE = 67,\r
+ STR_RECREATIONAL_SPORTS = 68,\r
+ STR_RECREATIONAL_SKATING = 69,\r
+ STR_RECREATIONAL_MARTIALARTS = 70,\r
+ STR_RECREATIONAL_TAICHI = 71,\r
+ STR_RECREATIONAL_HULAHOOP = 72,\r
+ STR_RECREATIONAL_DISCSPORT = 73,\r
+ STR_RECREATIONAL_DARTS = 74,\r
+ STR_RECREATIONAL_ARCHERY = 75,\r
+ STR_RECREATIONAL_HORSERIDING = 76,\r
+ STR_RECREATIONAL_BATTLEGAME = 77,\r
+ STR_RECREATIONAL_KITE = 78,\r
+ STR_RECREATIONAL_TUGOFWAR = 79,\r
+ STR_RECREATIONAL_SWING = 80,\r
+ STR_RECREATIONAL_STAIRCLIMBING = 81,\r
+ STR_RECREATIONAL_OBSTACLERACE = 82,\r
+ STR_RECREATIONAL_FISHING = 83,\r
+ STR_RECREATIONAL_HUNTING = 84,\r
+ STR_RECREATIONAL_SCOOTERRIDING = 85,\r
+ STR_RECREATIONAL_PARAGLIDING = 86,\r
+ STR_RECREATIONAL_TEAMSPORTS = 87,\r
+ STR_RECREATIONAL_FINESSGAMING = 88,\r
+ STR_RECREATIONAL_HIKING = 89,\r
+ STR_RECREATIONAL_EQUESTRIANSPORTS = 90,\r
+ STR_RECREATIONAL_PLAY = 91,\r
+ STR_BALL_GAMES = 92,\r
+ STR_BALL_BADMINTON = 93,\r
+ STR_BALL_TABLETENNIS = 94,\r
+ STR_BALL_TENNIS = 95,\r
+ STR_BALL_BILLIARDS = 96,\r
+ STR_BALL_BOWLING = 97,\r
+ STR_BALL_VOLLEYBALL = 98,\r
+ STR_BALL_SHUTTLECOCK = 99,\r
+ STR_BALL_HANDBALL = 100,\r
+ STR_BALL_BASEBALL = 101,\r
+ STR_BALL_SOFTBALL = 102,\r
+ STR_BALL_CRICKET = 103,\r
+ STR_BALL_FOOTBALL = 104,\r
+ STR_BALL_BEACHSOCCER = 105,\r
+ STR_BALL_BEACHVOLLEYBALL = 106,\r
+ STR_BALL_CROQUET = 107,\r
+ STR_BALL_HOCKEY = 108,\r
+ STR_BALL_SQUASH = 109,\r
+ STR_BALL_SEPAKTAKRAW = 110,\r
+ STR_BALL_DODGEBALL = 111,\r
+ STR_BALL_BASKETBALL = 112,\r
+ STR_BALL_SOCCER = 113,\r
+ STR_BALL_GOLF = 114,\r
+ STR_BALL_POLO = 115,\r
+ STR_BALL_RACQUETBALL = 116,\r
+ STR_BALL_RUGBY = 117,\r
+ STR_BALL_GATEBALL = 118,\r
+ STR_BALL_PICKLEBALL = 119,\r
+ STR_BALL_LACROSSE = 120,\r
+ STR_WATER_ACTIVITIES = 121,\r
+ STR_WATER_SAILING = 122,\r
+ STR_WATER_SURFING = 123,\r
+ STR_WATER_WHITEWATERRAFTING = 124,\r
+ STR_WATER_CANOEING = 125,\r
+ STR_WATER_KAYAKING = 126,\r
+ STR_WATER_ROWING = 127,\r
+ STR_WATER_MOTORBOAT = 128,\r
+ STR_WATER_SUP = 129,\r
+ STR_WATER_SCUBADIVING = 130,\r
+ STR_WATER_DIVING = 131,\r
+ STR_WATER_KITESURFING = 132,\r
+ STR_WATER_WAKEBOARDING = 133,\r
+ STR_WATER_POLO = 134,\r
+ STR_WATER_WINDSURFING = 135,\r
+ STR_WATER_DRIFTING = 136,\r
+ STR_WATER_FITNESS = 137,\r
+ STR_WATER_SPORTS = 138,\r
+ STR_WATER_OUTDOORSWIM = 139,\r
+ STR_WATER_INDOORSWIM = 140,\r
+ STR_WATER_SWIMFREESTYLE = 141,\r
+ STR_WATER_SWIMBREASTSTROKE = 142,\r
+ STR_WATER_SWIMBACKSTROKE = 143,\r
+ STR_WATER_SWIMBUTTERFLY = 144,\r
+ STR_ICE_SPORTS = 145,\r
+ STR_ICE_SKATING = 146,\r
+ STR_ICE_HOCKEY = 147,\r
+ STR_ICE_CURLING = 148,\r
+ STR_ICE_SNOWMOBILING = 149,\r
+ STR_ICE_SLED = 150,\r
+ STR_ICE_BIATHLON = 151,\r
+ STR_ICE_CROSSCOUNTRYSKING = 152,\r
+ STR_ICE_SKIING = 153,\r
+ STR_ICE_SNOWBOARDING = 154,\r
+ STR_ICE_SNOWSHOEING = 155,\r
+ STR_ICE_SNOWSPORTS = 156,\r
+ STR_EXTREME_SPORTS = 157,\r
+ STR_EXTREME_SKATEBOARDING = 158,\r
+ STR_EXTREME_ROCKCLIMBING = 159,\r
+ STR_EXTREME_BUNGEEJUMPING = 160,\r
+ STR_EXTREME_PARKOUR = 161,\r
+ STR_EXTREME_BMX = 162,\r
+ STR_EXTREME_ORIENTEERING = 163,\r
+ STR_EXTREME_PARACHUTE = 164,\r
+ STR_EXTREME_RACING = 165,\r
+ STR_EXTREME_TRIATHLONS = 166,\r
+ STR_OTHER_ELEVATOR = 167,\r
+ STR_OTHER_ESCALATOR = 168,\r
+ STR_OTHER_GARDENING = 169,\r
+ STR_OTHER_HORSEWORK = 170,\r
+ STR_OTHER_INVEHICLE = 171,\r
+ STR_OTHER_MEDITATION = 172,\r
+ STR_OTHER_STILL = 173,\r
+ STR_OTHER_TILTING = 174,\r
+ STR_OTHER_WHEELCHAIR = 175,\r
+ STR_HEART_RATE = 176,\r
+ STR_BLOOD_OXYGEN = 177,\r
+ STR_TRAINING = 178,\r
+ STR_TRAINING_RECORD = 179,\r
+ STR_COMPASS = 180,\r
+ STR_TELEPHONE = 181,\r
+ STR_FAVORITE_CONTACTS = 182,\r
+ STR_WEATHER = 183,\r
+ STR_ACTIVITY = 184,\r
+ STR_WATCH_FACE = 185,\r
+ STR_DISPLAY_MODE = 186,\r
+ STR_CARD_MANAGEMENT = 187,\r
+ STR_MUSIC = 188,\r
+ STR_SLEEP = 189,\r
+ STR_RECORD = 190,\r
+ STR_BREATH_TRAINING = 191,\r
+ STR_REMOTE_SHOOTING = 192,\r
+ STR_VOICE_ASSISTANT = 193,\r
+ STR_ALIPAY = 194,\r
+ STR_TIMER = 195,\r
+ STR_ALARM = 196,\r
+ STR_STOPWATCH = 197,\r
+ STR_CALCULATOR = 198,\r
+ STR_FIND_PHONE = 199,\r
+ STR_BRIGHTNESS_ADJUSTMENT = 200,\r
+ STR_SOUND = 201,\r
+ STR_BLUETOOTH = 202,\r
+ STR_DO_NOT_DISTURB = 203,\r
+ STR_MESSAGE_NOTIFICATION = 204,\r
+ STR_POWER_SAVE_MODE = 205,\r
+ STR_FLASHLIGHT = 206,\r
+ STR_SETTINGS = 207,\r
+ STR_EXERCISE_LIST = 208,\r
+ STR_BALL_LIST = 209,\r
+ STR_WATER_LIST = 210,\r
+ STR_DANCING_LIST = 211,\r
+ STR_EXTREME_LIST = 212,\r
+ STR_ICE_LIST = 213,\r
+ STR_RECREATIONAL_LIST = 214,\r
+ STR_OTHER_LIST = 215,\r
+ STR_DANCING_TITLE = 216,\r
+ STR_BALL_LIST_TITLE = 217,\r
+ STR_OTHER_TITLE = 218,\r
+ STR_EXERCISE_TITLE = 219,\r
+ STR_RAPID_TRAINING = 220,\r
+ STR_SET_GOALS = 221,\r
+ STR_DURATION = 222,\r
+ STR_DURATION_SETTING = 223,\r
+ STR_CALORIE = 224,\r
+ STR_CALORIE_SETTING = 225,\r
+ STR_DISTANCE = 226,\r
+ STR_RANGE_SETTING = 227,\r
+ STR_STEP_NUMBER = 228,\r
+ STR_STEP_SETTING = 229,\r
+ STR_HEART_RATE_SETTING = 230,\r
+ STR_MEAN_HEART_RATE = 231,\r
+ STR_TIMES_PER_MIN = 232,\r
+ STR_MEAN_HEART_RATE_MIN = 233,\r
+ STR_LOWER_STRENGTH = 234,\r
+ STR_MEDIUM_STRENGTH = 235,\r
+ STR_HIGH_STRENGTH = 236,\r
+ STR_ULTRA_HIGH_STRENGTH = 237,\r
+ STR_TRAINING_INTENSITY = 238,\r
+ STR_TRAINING_IN_PROGRESS = 239,\r
+ STR_BREAK_TRAINING = 240,\r
+ STR_FINISH = 241,\r
+ STR_PAUSE = 242,\r
+ STR_RESUME = 243,\r
+ STR_GOAL_ACHIEVED = 244,\r
+ STR_ACCOMPLISH_GOAL = 245,\r
+ STR_OK = 246,\r
+ STR_LOOK_OUT = 247,\r
+ STR_INSUFFICIENT_EXERCISE_AMOUNT = 248,\r
+ STR_END_MOVEMENT = 249,\r
+ STR_END_THIS_MOVEMENT = 250,\r
+ STR_GOAL_ACCOMPLISHMENT_DEGREE = 251,\r
+ STR_TRAINING_DURATION = 252,\r
+ STR_RANGE_MILE = 253,\r
+ STR_CLOSE = 254,\r
+ STR_MORE = 255,\r
+ STR_MORE_APP = 256,\r
+ STR_SAVENOTE = 257,\r
+ STR_SAVEBACK = 258,\r
+ STR_SAVEASK = 259,\r
+ STR_BLOOD = 260,\r
+ STR_CHECK = 261,\r
+ STR_CHECKNEW = 262,\r
+ STR_CHECKTIME = 263,\r
+ STR_CHECKLONG = 264,\r
+ STR_CHECKNO = 265,\r
+ STR_CHECKNOTE = 266,\r
+ STR_CHECKON = 267,\r
+ STR_CHECKSTOP = 268,\r
+ STR_CHECKERROR = 269,\r
+ STR_WAERKEEP = 270,\r
+ STR_WEARRE = 271,\r
+ STR_WEARREADY = 272,\r
+ STR_RECHECK = 273,\r
+ STR_CHECKEWARN = 274,\r
+ STR_BLOODSHORT = 275,\r
+ STR_HEARTNOTE = 276,\r
+ STR_KONW = 277,\r
+ STR_EXPLAIN = 278,\r
+ STR_HEARTREST = 279,\r
+ STR_HEARTDATA = 280,\r
+ STR_HEARTTITLE = 281,\r
+ STR_HEARTMAX = 282,\r
+ STR_HEARTMIN = 283,\r
+ STR_TRAINGNO = 284,\r
+ STR_TRAINGGO = 285,\r
+ STR_MESSAGENO = 286,\r
+ STR_CLEAN = 287,\r
+ STR_CLEANALL = 288,\r
+ STR_SLEEP_YESTERDAY = 289,\r
+ STR_HOUR = 290,\r
+ STR_MIN = 291,\r
+ STR_SLEEPMGOAL = 292,\r
+ STR_REATTIME = 293,\r
+ STR_SLEEPTIME = 294,\r
+ STR_WALKTIME = 295,\r
+ STR_APPMORE = 296,\r
+ STR_DISTURB = 297,\r
+ STR_DISTURBNOTE = 298,\r
+ STR_MORNNING = 299,\r
+ STR_NOW = 300,\r
+ STR_NAP = 301,\r
+ STR_TACK = 302,\r
+ STR_CLICK = 303,\r
+ STR_TACKNUM = 304,\r
+ STR_SCREEN_AND_BRIGHTNESS = 305,\r
+ STR_NETWORKANDCALL = 306,\r
+ STR_SOUND_AND_VIBRATION = 307,\r
+ STR_MOTION_RECOGNITION = 308,\r
+ STR_SYSTEM = 309,\r
+ STR_SHUTDOWN_AND_RESTART = 310,\r
+ STR_SCREEN_ON_DURATION = 311,\r
+ STR_RAISE_TO_WAKE = 312,\r
+ STR_5_SECONDS = 313,\r
+ STR_10_SECONDS = 314,\r
+ STR_15_SECONDS = 315,\r
+ STR_30_SECONDS = 316,\r
+ STR_60_SECONDS = 317,\r
+ STR_300_SECONDS = 318,\r
+ STR_4G_CAPABILITY = 319,\r
+ STR_VOLTE_CALL = 320,\r
+ STR_MOBILE_DATA_OPTION = 321,\r
+ STR_SYSTEM_UPDATE = 322,\r
+ STR_ONLINE_MUSIC = 323,\r
+ STR_BLUETOOTH_HEADPHONES = 324,\r
+ STR_TRADITIONAL_BLUETOOTH = 325,\r
+ STR_AUTO_OFF_BLUETOOTH_NOTE = 326,\r
+ STR_BLUETOOTH_SERVICE_OPTIONS = 327,\r
+ STR_HFP = 328,\r
+ STR_A2DP = 329,\r
+ STR_SYSTEM_VOLUME = 330,\r
+ STR_MEDIA_VOLUME = 331,\r
+ STR_CALL_VOLUME = 332,\r
+ STR_VIBRATION_MODE = 333,\r
+ STR_SILENT_MODE = 334,\r
+ STR_LIST_DISPLAY = 335,\r
+ STR_GRID_DISPLAY = 336,\r
+ STR_CELLULAR_DISPLAY = 337,\r
+ STR_AUTO_DETECT = 338,\r
+ STR_ABOUT_WATCH = 339,\r
+ STR_WATCH_QR_CODE = 340,\r
+ STR_SYSTEM_LANGUAGE = 341,\r
+ STR_RESTART = 342,\r
+ STR_SHUTDOWN = 343,\r
+ STR_FACTORY_RESET = 344,\r
+ STR_WATCH_NAME = 345,\r
+ STR_FIRMWARE_VERSION = 346,\r
+ STR_BLUETOOTH_NAME = 347,\r
+ STR_BLUETOOTH_ADDRESS = 348,\r
+ STR_UPDATENOW = 349,\r
+ STR_LATEST_VERSION = 350,\r
+ STR_LATER = 351,\r
+ STR_UP_TO_DATE = 352,\r
+ STR_NO_UPDATE = 353,\r
+ STR_LANGUAGE_SELECTION = 354,\r
+ STR_RESET_CONFIRM = 355,\r
+ STR_SHUTDOWN_CONFIRM = 356,\r
+ STR_RESET_CONFIRM_NOTE = 357,\r
+ STR_RECORDER = 358,\r
+ STR_CLICK_TO_RECORD = 359,\r
+ STR_RECORDING = 360,\r
+ STR_AUDIO_XX = 361,\r
+ STR_VOICE_RECORDING_REMINDER = 362,\r
+ STR_VOICE_RECORDING_REMINDER_NOTE = 363,\r
+ STR_DELETE_RECORDING = 364,\r
+ STR_DELETE_PERMANENTLY = 365,\r
+ STR_RECORDING_LIST = 366,\r
+ STR_CRLEMPTY = 367,\r
+ STR_DO_NOT_DISTURB_MODE = 368,\r
+ STR_CONNECTION_STATUS = 369,\r
+ STR_PHONE = 370,\r
+ STR_HEADSET = 371,\r
+ STR_CONNECTED = 372,\r
+ STR_DISCONNECTED = 373,\r
+ STR_PHONE_RINGING_VIBRATING = 374,\r
+ STR_BLUETOOTH_DISCONNECTED = 375,\r
+ STR_STOP = 376,\r
+ STR_WORKDAY = 377,\r
+ STR_REPEAT_NO = 378,\r
+ STR_EVERYDAY = 379,\r
+ STR_ADD_A_NEW_ALARM = 380,\r
+ STR_TIME = 381,\r
+ STR_NEXT_STEP = 382,\r
+ STR_MON = 383,\r
+ STR_TUES = 384,\r
+ STR_WEDNES = 385,\r
+ STR_THURS = 386,\r
+ STR_FRI = 387,\r
+ STR_SATUR = 388,\r
+ STR_SUN = 389,\r
+ STR_MONDAY = 390,\r
+ STR_TUESDAY = 391,\r
+ STR_WEDNESDAY = 392,\r
+ STR_THURSDAY = 393,\r
+ STR_FRIDAY = 394,\r
+ STR_SATURDAY = 395,\r
+ STR_SUNDAY = 396,\r
+ STR_CALIBRATE_COMPASS = 397,\r
+ STR_CALIBRATE_COMPASS_NOTE = 398,\r
+ STR_EAST = 399,\r
+ STR_SOUTH = 400,\r
+ STR_WEST = 401,\r
+ STR_NORTH = 402,\r
+ STR_SOUTHEAST = 403,\r
+ STR_SOUTHWEST = 404,\r
+ STR_NORTHEAST = 405,\r
+ STR_NORTHWEST = 406,\r
+ STR_KEEP_STILL_FOCUS_ON_BREATHING = 407,\r
+ STR_EXHALE_NOW = 408,\r
+ STR_INHALE_NOW = 409,\r
+ STR_TRAINING_COMPLETE = 410,\r
+ STR_THIS_BREATH = 411,\r
+ STR_TODAYS_BREATHING_TRAINING = 412,\r
+ STR_RECENT_CALLS = 413,\r
+ STR_NO_CALLS = 414,\r
+ STR_MISSED_CALLS = 415,\r
+ STR_DIALED_CALLS = 416,\r
+ STR_RECEIVED_CALLS = 417,\r
+ STR_NOTE_RECENT_CALLS_LIMITATION = 418,\r
+ STR_NO_CONTACTS_ADDED = 419,\r
+ STR_DIAL_MODE = 420,\r
+ STR_DIAL_VIA_WATCH_SIM = 421,\r
+ STR_DIAL_VIA_PHONE = 422,\r
+ STR_KUMI_TECHNOLOGY = 423,\r
+ STR_CALLING = 424,\r
+ STR_NOT_PAIRED = 425,\r
+ STR_PAIRED = 426,\r
+ STR_UNPAIR = 427,\r
+ STR_CONNECTION_ERROR = 428,\r
+ STR_INSERT_WATCH_SIM_OR_CONNECT_PHONE = 429,\r
+ STR_ENABLE_BLUETOOTH_CALL = 430,\r
+ STR_SOLUTION = 431,\r
+ STR_IPHONE = 432,\r
+ STR_ANDROID = 433,\r
+ STR_ENABLE_BLUETOOTH_CALL_NOTE_IPHONE = 434,\r
+ STR_ENABLE_BLUETOOTH_CALL_NOTE_ANDROID = 435,\r
+ STR_SIM_CARD_ERROR = 436,\r
+ STR_CHECK_SIM_CARD_INSERTION = 437,\r
+ STR_WEATHER_REPORT = 438,\r
+ STR_ULTRAVIOLET = 439,\r
+ STR_WIND_SPEED = 440,\r
+ STR_HUMIDITY = 441,\r
+ STR_NEXT_7_DAYS = 442,\r
+ STR_GET_WEATHER_ERROR = 443,\r
+ STR_MUSIC_SOURCE = 444,\r
+ STR_MOBILE_MUSIC = 445,\r
+ STR_WATCH_MUSIC = 446,\r
+ STR_MUSIC_LIST = 447,\r
+ STR_BLUETOOTH_CONNECTION_FAILED = 448,\r
+ STR_SCANNING_BINDING = 449,\r
+ STR_DEVICE_BINDING = 450,\r
+ STR_DEVICE_BINDING_NOTE = 451,\r
+ STR_EQUIPMENT_UNTYING = 452,\r
+ STR_EQUIPMENT_UNTYING_NOTE = 453,\r
+ STR_DRINK_WATER_REMINDER = 454,\r
+ STR_DRINK_WATER_REMINDER_NOTE = 455,\r
+ STR_SEDENTARY_REMINDER = 456,\r
+ STR_SEDENTARY_REMINDER_NOTE = 457,\r
+ STR_SYSTEM_UPGRADING = 458,\r
+ STR_NEWDEVICE_BIND_REMIND_NOTE1 = 459,\r
+ STR_NEWDEVICE_BIND_REMIND_NOTE2 = 460,\r
+ STR_NEWDEVICE_BIND_REMIND_NOTE3 = 461,\r
+ STR_AI_VOICE = 462,\r
+ STR_AI_INTELLIGENT_ASSISTANT = 463,\r
+ STR_START_CHAT = 464,\r
+ STR_BOOT_FAILED = 465,\r
+ STR_ENABLE_MOBILE_DATA_FIRST = 466,\r
+ STR_ENABLE_BLUETOOTH_FIRST = 467,\r
+ STR_LISTENING = 468,\r
+ STR_FINISH_SPEAKING = 469,\r
+ STR_THINKING = 470,\r
+ STR_CANCEL = 471,\r
+ STR_CONNECT_TIMEOUT = 472,\r
+ STR_PLEASE_RESTART_CHAT = 473,\r
+ STR_CONTINUE_CHAT = 474,\r
+ STR_AIMODELS_DOUBAO = 475,\r
+ STR_AIMODES_WENXINYIYAN = 476,\r
+ STR_AIMODES_KIMI = 477,\r
+ STR_AIMODES_CHATGPT = 478,\r
+ STR_SLIDE_TO_SHUTDOWN = 479,\r
+ STR_SLIDE_TO_REBOOT = 480,\r
+ STR_AI_FAMILY_MEALS = 481,\r
+ STR_CHAT = 482,\r
+ STR_PCY4GC_OR_AS = 483,\r
+ STR_API_KEYS = 484,\r
+ STR_PGTTAF = 485,\r
+ STR_DAFBS = 486,\r
+ STR_OPENAI_API_KEYS = 487,\r
+ STR_KHBB = 488,\r
+ STR_GTAS = 489,\r
+ STR_DYWTDAK = 490,\r
+ STR_CONNECTING = 491,\r
+ STR_CONNECTION_FAIL = 492,\r
+ STR_PTALORTM = 493,\r
+ STR_MOTION_DETECTION_WALK_NOTE = 494,\r
+ STR_MOTION_DETECTION_RUN_NOTE = 495,\r
+ STR_MOTION_DETECTION_RIDE_NOTE = 496,\r
+ STR_MOTION_DETECTION_ROWING_NOTE = 497,\r
+ STR_MOTION_DETECTION_ELLIPTICAL_NOTE = 498,\r
+ STR_PE4GC = 499,\r
+ STR_OBU_MESSAGE = 500,\r
+ STR_DELETE = 501,\r
+ STR_CHARGE = 502,\r
+ STR_CHARGE_NOTE = 503,\r
+ STR_STEP_FREQUENCY = 504,\r
+ STR_STEP_LENGTH = 505,\r
+ STR_AVG_PACE = 506,\r
+ STR_TONGYI_QIANWEN = 507,\r
+ STR_IFLYTEK_SPARK = 508,\r
+ STR_DISTURBNOTE_OFF = 509,\r
+ STR_4G_NOTE = 510,\r
+ STR_MUSIC_PLAYER_SOURCE_NOTE = 511,\r
+ STR_MUSIC_LIST_IS_EMPTY = 512,\r
+ STR_BT_HEADSET_RESCAN = 513,\r
+ STR_BT_HEADSET_NOFOND = 514,\r
+ STR_SCHEDULE = 515,\r
+ STR_SCHEDULE_TITLE = 516,\r
+ STR_SCHEDULE_NO_DATA = 517,\r
+ STR_SCHEDULE_NO_DATA_PROMPT = 518,\r
+ STR_NO_PAIRED_DEV = 519,\r
+ STR_IGNORE = 520,\r
+ STR_START = 521,\r
+ STR_ARC_SCALE_LIST_DISPLAY = 522,\r
+ STR_COUNT_DOWN = 523,\r
+ STR_CUSTOM_TIME = 524,\r
+ STR_QUICK_START = 525,\r
+ STR_1_MIN = 526,\r
+ STR_5_MIN = 527,\r
+ STR_10_MIN = 528,\r
+ STR_30_MIN = 529,\r
+ STR_SET_COUNT_DOWN_NOTE = 530,\r
+ STR_COUNTDOWN_ENDS = 531,\r
+ STR_MAXIMUM_TIME_REACH_NOTE = 532,\r
+ STR_STOPWATCH_STOP_NOTE = 533,\r
+ STR_TMCHBR = 534,\r
+ STR_SCHEDULE_TOPIC = 535,\r
+ STR_SCHEDULE_TIME = 536,\r
+ STR_SCHEDULE_NOTES = 537,\r
+ STR_SCHEDULE_DELETE_PROMPT = 538,\r
+ STR_HANG_UP_OR_ANSWER = 539,\r
+ STR_WATCH_CALL = 540,\r
+ STR_PHONE_CALL = 541,\r
+ STR_STEPS_OF_THE_DAY = 542,\r
+ STR_MILEAGE = 543,\r
+ STR_FAT_BURNING_TIME = 544,\r
+ STR_NUMBER_OF_STANDS = 545,\r
+ STR_CONSUME_CALORIES = 546,\r
+ STR_GOAL_HINT = 547,\r
+ STR_SLEEPMODE = 548,\r
+ STR_SLEEP_MODE_PROMPT_ON = 549,\r
+ STR_LOW_POWER_NOTIF_1 = 550,\r
+ STR_LOW_POWER_NOTIF_2 = 551,\r
+ STR_CONNECTION_SUCC = 552,\r
+ STR_RETRY = 553,\r
+ STR_BTEARPHONE_CONN_FAIL_TIP = 554,\r
+ STR_FLASHLIGHT_SETTING = 555,\r
+ STR_LIGHT_COLOR = 556,\r
+ STR_FLICKER_FREQUENCY = 557,\r
+ STR_NO_FLICKER = 558,\r
+ STR_FAST_FLICKER = 559,\r
+ STR_SLOW_FLICKER = 560,\r
+ STR_BROWSING_SPECIAL_EFFECTS = 561,\r
+ STR_OVERLAY_FLOW = 562,\r
+ STR_ROLLER = 563,\r
+ STR_DIAL_BROWSING_SPECIAL_EFFECTS = 564,\r
+ STR_SET_TARGET = 565,\r
+ STR_PWUWC = 566,\r
+ STR_CALENDAR = 567,\r
+ STR_ALARM_DELETE_NOTE = 568,\r
+ STR_ALARM_TIME_CHANGE = 569,\r
+ STR_ALARM_WEEK_CHANGE = 570,\r
+ STR_ALARM_REPEAT = 571,\r
+ STR_ALARM_ADD_LIMIT_NOTE = 572,\r
+ STR_MOTION_RECOGNITION_NOTE = 573,\r
+ STR_DURATION_SETTINGS = 574,\r
+ STR_2_MIN = 575,\r
+ STR_3_MIN = 576,\r
+ STR_4_MIN = 577,\r
+ STR_ONE_MIN = 578,\r
+ STR_TWO_MIN = 579,\r
+ STR_THREE_MIN = 580,\r
+ STR_FOUR_MIN = 581,\r
+ STR_FIVE_MIN = 582,\r
+ STR_MUSIC_TRANSMIT = 583,\r
+ STR_MUSIC_TRANSMIT_NOTE = 584,\r
+ STR_MUSIC_TRANSMIT_SUCCESS_NOTE = 585,\r
+ STR_OTA_DOWNLOAD = 586,\r
+ STR_OTA_DOWNLOADING = 587,\r
+ STR_OTA_DOWNLOADFIAL = 588,\r
+ STR_OTA_DOWNLOADFIAL_TRY = 589,\r
+ STR_OTA_DOWNLOADSUCC = 590,\r
+ STR_OTA_DOWNLOADSUCC_UPDATA = 591,\r
+ STR_DIAL_DOWNLOADING_TITLE = 592,\r
+ STR_DIAL_DOWNLOADING_LABEL = 593,\r
+ STR_MP3_SUCC_TITLE = 594,\r
+ STR_DIAL_SUCC_TITLE = 595,\r
+ STR_DIAL_SUCC_LABEL = 596,\r
+ STR_DIAL_FAIL_TITLE = 597,\r
+ STR_DIAL_FAIL_LABEL = 598,\r
+ STR_MP3_FAIL_TITL = 599,\r
+ STR_MP3_FAIL_LABEL = 600,\r
+ STR_CALLSOMEONE = 601,\r
+ STR_BLUENOTE = 602,\r
+ STR_VOICE_FAIL = 603,\r
+ STR_WAKE_VOIVE = 604,\r
+ STR_TIME_SET = 605,\r
+ STR_FORMAT = 606,\r
+ STR_FORMAT_NOTE = 607,\r
+ STR_SLEEP_UPDATE = 608,\r
+ STR_CAMERA = 609,\r
+ STR_GOAL_TITLE = 610,\r
+ STR_HEART_HIAGER = 611,\r
+ STR_CHARG_DOWN = 612,\r
+ STR_CHAEGING = 613,\r
+ STR_GOAL_DOWN = 614,\r
+ STR_OPERAT_FAIL = 615,\r
+ STR_DIAL_NOTE = 616,\r
+ STR_HEART_UNKOWN = 617,\r
+ STR_HEART_AVAILABLE = 618,\r
+ STR_HEART_JUST = 619,\r
+ STR_HEART_MIN_AGO = 620,\r
+ STR_HEART_HOUR_AGO = 621,\r
+ STR_RECORDS_20 = 622,\r
+ STR_RECORDS_NOTE = 623,\r
+ STR_RECORDS_DELETE = 624,\r
+ STR_NEW_INCOM = 625,\r
+ STR_NET_ERROR = 626,\r
+ STR_LANGUAGE_SELECTION_NOTE = 627,\r
+ STR_AUTO_OFF_BLUETOOTH_NOTE2 = 628,\r
+ STR_PHONE_MUSCI_NOTE = 629,\r
+ STR_TIME_FORMAT_SET = 630,\r
+ STR_DIAL_PLATE = 631,\r
+ STR_SLEEP_NOTIFY = 632,\r
+ STR_SLEEP_NOTE = 633,\r
+ STR_MAX_CARD = 634,\r
+ STR_NUM_LENGTH = 635,\r
+ STR_CALL_LIST = 636,\r
+ STR_DELETE_ALL = 637,\r
+ STR_FRE_CONTACT = 638,\r
+ STR_RECORD_MAX = 639,\r
+ STR_CLEAR_ALL_RECORDS = 640,\r
+ STR_DEEPSEEK = 641,\r
+ STR_BP_CHECK = 642,\r
+ STR_BP_CALIBRATE = 643,\r
+ STR_MEARURING = 644,\r
+ STR_MEASURING_KEEP_STILL = 645,\r
+ STR_RECALIBRATE = 646,\r
+ STR_CALIBRATION_DONE = 647,\r
+ STR_CALIBRATION_FAILED = 648,\r
+ STR_MEASUREMENT_DONE = 649,\r
+ STR_CALIBRATION_REMINDER = 650,\r
+ STR_USE_TRAD_SPHYGM = 651,\r
+ STR_CONFIRM = 652,\r
+ STR_CAL_RES_UPLOADED_30D = 653,\r
+ STR_RES_ANALYZING = 654,\r
+ STR_ANALYZING_DONT_EXIT = 655,\r
+ STR_FIRST_CAL_KEEP_STILL = 656,\r
+ STR_SECOND_CAL_KEEP_STILL = 657,\r
+ STR_ENTER_BP_READ = 658,\r
+ STR_SBP = 659,\r
+ STR_DBP = 660,\r
+ STR_NORMAL = 661,\r
+ STR_ELEVATED = 662,\r
+ STR_WARNING = 663,\r
+ STR_SBP_ELEVATED = 664,\r
+ STR_WARN_THRESH = 665,\r
+ STR_BP_WARN_CONSULT_DOC = 666,\r
+ STR_MEAS_FAILED = 667,\r
+ STR_CALIBRATING = 668,\r
+ STR_S = 669,\r
+ STR_PRESSURE = 670,\r
+ STR_WEAR_WATCH_DET = 671,\r
+ STR_RE_MEAS = 672,\r
+ STR_DATA_ANAL_WAIT = 673,\r
+ STR_EMOTION = 674,\r
+ STR_PLEASURE = 675,\r
+ STR_COMPLEX_NEG_EMO = 676,\r
+ STR_MEASURE = 677,\r
+ STR_FINGER_LEAD_PORT = 678,\r
+ STR_START_MEAS = 679,\r
+ STR_WEAR_TIGHT_FINGER_LEAD = 680,\r
+ STR_NO_FINGER_MOVE = 681,\r
+ STR_CONNECT_APP_4G = 682,\r
+ STR_FINGER_LEAD_TILL_VAL = 683,\r
+ STR_SINUS_HR = 684,\r
+ STR_APP_REPORT_NOT_CLIN = 685,\r
+ STR_FATIGUE_LEVEL = 686,\r
+ STR_BP_MODEL_2CAL = 687,\r
+ STR_RECAL_MONTHLY = 688,\r
+ STR_SAME_ARM_CALIB = 689,\r
+ STR_HYPERTENSIVE_PREPOST_CAL = 690,\r
+ STR_CALIB_POSTURE_GUIDE = 691,\r
+ STR_START_CAL = 692,\r
+ STR_CALIB_POSTURE_REQ = 693,\r
+ STR_ECG = 694,\r
+ STR_JIUTIAN = 695,\r
+ STR_LAST_CALIBRATION_TIME = 696,\r
+ STR_CALIBRATE = 697,\r
+ STR_CALIBRATION_SUGGESTION = 698,\r
+ STR_CALIBRATION_PATH = 699,\r
+ STR_MAX_ID = 700,\r
+}; // UIResourceTextId\r
+
+enum FontLanguageId : uint8_t {
+ LANGUAGE_ID_AR,\r
+ LANGUAGE_ID_AZ,\r
+ LANGUAGE_ID_CS,\r
+ LANGUAGE_ID_DE,\r
+ LANGUAGE_ID_EL,\r
+ LANGUAGE_ID_EN,\r
+ LANGUAGE_ID_ES,\r
+ LANGUAGE_ID_FA,\r
+ LANGUAGE_ID_FI,\r
+ LANGUAGE_ID_FR,\r
+ LANGUAGE_ID_HE,\r
+ LANGUAGE_ID_HI,\r
+ LANGUAGE_ID_HR,\r
+ LANGUAGE_ID_ID,\r
+ LANGUAGE_ID_IT,\r
+ LANGUAGE_ID_JA,\r
+ LANGUAGE_ID_KO,\r
+ LANGUAGE_ID_MS,\r
+ LANGUAGE_ID_NL,\r
+ LANGUAGE_ID_PL,\r
+ LANGUAGE_ID_PT,\r
+ LANGUAGE_ID_RO,\r
+ LANGUAGE_ID_RU,\r
+ LANGUAGE_ID_SV,\r
+ LANGUAGE_ID_TH,\r
+ LANGUAGE_ID_TR,\r
+ LANGUAGE_ID_UK,\r
+ LANGUAGE_ID_UZ,\r
+ LANGUAGE_ID_VI,\r
+ LANGUAGE_ID_ZH,\r
+ LANGUAGE_ID_MAX\r
+}; // UITextLanguageTextId\r
+}\r
+#endif /* UI_RESOURCE_STRING_H */\r
--- /dev/null
+16
\ No newline at end of file
--- /dev/null
+import _thread
+import usys
+import ql_fs
+CHINA_TELECOM_DM_FUN_ENABLE = 1 #是否开启电信入库的功能
+CHINA_MOBILE_DM_FUN_ENABLE = 1 #开启移动入库功能
+class EventStore(object):
+ def __init__(self):
+ self.map = dict()
+ self.log = None
+ self.__filters = []
+
+ def add_filter(self, flt):
+ self.__filters.append(flt)
+
+ def append(self, event, cb):
+ self.map[event] = cb
+
+ def fire_async(self, event, msg,thread_size):
+ if event in self.map:
+ #print("fire_async:thread_size:{}".format(thread_size))
+ if thread_size != None:
+ _thread.stack_size(thread_size)
+ #print("fire_async:thread_size:{}".format(thread_size))
+ _thread.start_new_thread(self.map[event], (event, msg))
+ if thread_size != None:
+ _thread.stack_size(8*1024)
+ if self.log:
+ self.log.info("ASYNC executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, None))
+
+ def fire_sync(self, event, msg):
+ res = None
+ try:
+ if event in self.map:
+ res = self.map[event](event, msg)
+ except Exception as e:
+ usys.print_exception(e)
+ if self.log:
+ self.log.info("ERROR executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, res))
+ if event not in self.__filters:
+ if self.log:
+ self.log.info("SYNC executed (event) -> {} (params) -> {} (result) -> {}".format(event, msg, res))
+ return res
+
+ def subscribe(self,event, cb):
+ """
+ subscribe event and cb
+ """
+ return self.append(event, cb)
+
+
+ def publish(self,event, msg=None):
+ """
+ publish event and msg
+ """
+ return self.publish_sync(event, msg)
+
+
+ def publish_async(self,event, msg=None,thread_size = None):
+ """
+ 异步发送
+ """
+ return self.fire_async(event, msg,thread_size)
+
+
+ def publish_sync(self,event, msg=None):
+ """
+ 同步发送
+ """
+ return self.fire_sync(event, msg)
+
+
+ def set_log(self,log_adapter):
+ self,log = log_adapter
+
+
+ def add_filter(self,flt):
+ self.add_filter(flt)
+
+eventMesh = EventStore()
+
+
+
+
+
+
+
--- /dev/null
+# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+# net.getNetMode()
+# (0, '460', '11', 7)
+
+# net.getSignal(1)
+# ([99, 99, 255, 255], [-84, -117, -15, 255, -3])
+
+# net.nitzTime()
+# ('24/02/26 11:17:42 8 0', 1708946262, 0)
+
+
+import usocket
+import log
+import utime
+import slip
+import audio
+from machine import UART
+import _thread
+from queue import Queue
+from machine import Pin
+from machine import ExtInt
+import dataCall
+import voiceCall
+import net
+import uping
+import example
+import osTimer
+import sim
+import modem
+import utime
+import checkNet
+import atcmd
+import fota
+import request
+import ql_fs
+import pm
+import sms
+
+from usr.EventMesh import eventMesh
+from usr.httpota import httpota
+# from usr.telecom_dmp import telecomDmpCb
+# from usr.china_mobile_dmp import chinamobileCb
+from usr.china_mobile_ai_regulation import aiRegulation
+# 设置日志输出级别
+log.basicConfig(level=log.INFO)
+clog = log.getLogger("cat1")
+
+def msg_cb(args):
+ index = args[1]
+ storage = args[2]
+ sms_data = sms.getSaveLoc()
+ if sms_data == -1:
+ return
+ sms_max = sms_data[0][2]
+ if index != -1:
+ eventMesh.publish("send_singal_data_toBle",index)
+
+ if index >= sms_max-1:#删除短信
+ eventMesh.publish("delete_sms_event")#删除短信
+
+sms.setCallback(msg_cb)#sms注册回调
+
+CAT1_SERVICE_HEAD = 'FE' #固定head
+
+PROJECT_NAME = "Cat1SlipUDPService"
+PROJECT_VERSION = "PY_SRV_V19"
+CONFIG_JSON="/usr/system_config.json"
+CURRENT_APP_TYPE="pysrv"
+
+
+
+
+
+
+#设置通话音量
+voiceCall.setVolume(10)
+clog.info("voice call volume {}".format(voiceCall.getVolume()))
+lpm_fd = pm.create_wakelock("system_lock", len("system_lock"))
+# pm.autosleep(1)
+pm.wakelock_lock(lpm_fd)
+clog.info("create_wakelock {}".format(pm.get_wakelock_num()))
+telecomTimerCount = 0
+def get_versionkeyname_by_py(app_type):
+ return str("{}version".format(app_type))
+
+def get_default_versionvalue_by_py(app_type):
+ if (app_type == "pymain"):
+ return "PY_MAIN_V2"
+ elif (app_type == "pyota"):
+ return "PY_OTA_V14"
+ elif (app_type == "pysrv"):
+ return "PY_SRV_V16"
+
+#如果没有configfile则创建它
+if not ql_fs.path_exists(CONFIG_JSON):
+ data = {str(get_versionkeyname_by_py(CURRENT_APP_TYPE)):get_default_versionvalue_by_py(CURRENT_APP_TYPE)}
+ ql_fs.touch(CONFIG_JSON,data)
+
+def set_version_to_json_config(app_type,keyvalue):
+ try :
+ config_data = ql_fs.read_json(CONFIG_JSON)
+ config_data.update( {str(get_versionkeyname_by_py(app_type)):keyvalue})
+ ql_fs.touch(CONFIG_JSON, config_data)
+ clog.info("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue))
+ clog.info("{}".format(config_data))
+ except Exception as e:
+ clog.error("set_version_to_json_config")
+
+def get_version_from_json_config(app_type):
+ config_data = ql_fs.read_json(CONFIG_JSON)
+ keyvalue = config_data.get( get_versionkeyname_by_py(app_type),get_default_versionvalue_by_py(app_type))
+ clog.info("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue))
+ return keyvalue
+
+set_version_to_json_config(CURRENT_APP_TYPE,PROJECT_VERSION)
+
+
+audio.set_qdai_cfg(1,0,0,1,0,0,1,1)
+
+# GPIO21 - 引脚 86 KP_MKOUT1 唤醒主控
+# GPIO22 - 引脚 87 KP_MKIN 被主控唤醒
+
+# GPIOn - GPIO号,int类型,点此查看GPIO引脚编号与物理引脚的映射关系。
+
+# direction - 输入输出模式,int类型,IN - 输入模式,OUT - 输出模式。
+
+# pullMode - 上下拉模式,int类型,说明如下:
+# PULL_DISABLE - 浮空模式
+# PULL_PU - 上拉模式
+# PULL_PD - 下拉模式
+
+# level - 引脚电平,int类型,0 - 设置引脚为低电平, 1- 设置引脚为高电平。
+# recvDataPin = Pin(Pin.GPIO22, Pin.IN, Pin.PULL_PU, 0)
+def ExtIntfun(args):
+ # clog.info('### interrupt {} ###'.format(args)) # args[0]:gpio号 args[1]:上升沿或下降沿
+ if args[1] == 0:
+ clog.info("disable autosleep")
+ # pm.autosleep(0)
+ pm.wakelock_lock(lpm_fd)
+ elif args[1] == 1:
+ clog.info("enable autosleep")
+ pm.wakelock_unlock(lpm_fd)
+ # pm.autosleep(1)
+ # clog.info("recvDataPin={}".format(recvDataPin.read()))
+extint = ExtInt(ExtInt.GPIO22, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_DISABLE, ExtIntfun)
+extint.enable()
+
+
+# 创建gpio对象
+gpioWakeBT = Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_DISABLE, 1)
+# 设置输入输出模式
+gpioWakeBT.set_dir(Pin.OUT)
+
+# 设置引脚电平
+gpioWakeBT.write(0)
+
+UDP_CMD_GET_CAT1VER = '0' #获取 Cat1 版本号
+UDP_CMD_DIAL_NUMB = '1' #拨打电话
+UDP_CMD_HUNGUP = '2' #挂断电话
+UDP_CMD_ANSWER = '3' #接听电话
+UDP_CMD_CAT1_OTA_UPDATE = '4' #触发Cat1 OTA升级,mcu提供url
+UDP_CMD_SEND_SMS = '5' #发送SMS短信,mcu提供电话号及短信内容
+UDP_CMD_GET_TIME = '6' #获取Cat1 时间 ,YYYYMMDD HHmmss zone
+UDP_CMD_GET_RECV_NETWORKSTAT = '7' #获取Cat1 信号信息,VOLTE信息,信号强度,SIM卡状态 // 内容同UDP_CMD_GET_NETWORKSTAT,CAT主动发给MCU
+UDP_MSG_SMS = '8' # CAT1接收到的SMS信息给MCU,包含电话号及短信内容
+UDP_CMD_ATCMD = '9' # 执行AT指令
+UDP_MSG_CALL_CONNECTED = 'A' # CAT1 电话接听消息
+UDP_MSG_CALL_DISCONNECTED = 'B' # CAT1 电话挂断消息
+UDP_MSG_COMMING_CALL = 'C' # CAT1 来电消息,包含电话号
+UDP_MSG_REPLY = 'F' # 返回值
+UDP_MSG_OTA = 'D' # 返回值
+
+class Cat1Service:
+ AP = 0 # SLIP_INNER
+ STA = 1 # SLIP_OUTER
+
+ def __init__(self, uart=UART.UART4, mode=AP):
+
+ self.__uart = uart
+ self.__mode = mode
+ self.__message = ''
+ self.__err = 0
+ self.__net_connected = 0
+ # self.__value = None
+ self.__wait_resp = 0
+ self.__waiting_netstat = 0
+ slip.destroy()
+ clog.info('slip uart={0}'.format (self.__uart))
+
+ ret = slip.construct(self.__uart, self.__mode, 0)
+ if ret != 0:
+ clog.error('slip netif construct fail')
+ return None
+ clog.info('slip network card create success')
+ # self.__queue = Queue(1)
+ self.__sock = self.__socket_init()
+ self.__threadid = _thread.start_new_thread(self.__Socket_Thread, ())
+ self.telecom_init_flag = 0
+ self.telecomTimer = osTimer()
+ eventMesh.subscribe("cat1_reply_iccid_to_ble",self.cat1_reply_iccid_to_ble)
+ eventMesh.subscribe("cat1_reply_timesec_to_ble",self.cat1_reply_timesec_to_ble)
+
+ self.iccid_data = ""
+ self.software_version = ""
+ self.deletSmsTimer = osTimer()
+ self.china_mobile_ai_init = 0
+ self.volte_switch = 1 #默认是开启VOLTE通话功能
+ eventMesh.subscribe("set_dmp_change_mode",self.set_dmp_change_mode)
+ eventMesh.subscribe("get_dmp_change_mode",self.get_dmp_change_mode)
+ eventMesh.subscribe("delete_sms_event",self.delete_sms_event)
+ eventMesh.subscribe("remove_all_sms_cb", self.remove_all_sms_cb)#
+ eventMesh.subscribe("send_sms_max_to_Ble",self.send_sms_max_to_Ble)
+ eventMesh.subscribe("get_all_sms_data",self.get_all_sms_data) #获取所有的短信内容
+ eventMesh.subscribe("send_singal_data_toBle",self.send_singal_data_toBle)
+ eventMesh.subscribe("delete_sms_single_data",self.delete_sms_single_data)
+
+ eventMesh.subscribe("get_factory_status",self.get_factory_status)
+ eventMesh.subscribe("set_factory_status",self.set_factory_status)
+ eventMesh.subscribe("send_dmp_cm_address_toBLE",self.send_dmp_cm_address_toBLE)
+ eventMesh.subscribe("set_volte_switch",self.set_volte_switch)
+ eventMesh.subscribe("get_volte_switch",self.get_volte_switch)
+ eventMesh.publish("delete_sms_event")
+
+
+ self.telecom_dmp_switch = 0
+
+ self.send_data = []
+ self.code_old = 0
+ self.code_old_num = 1
+ self.tmp_data = []
+ self.total_num = 0
+ #
+ self.msg_nums = 0
+ self.msg_nums_old = 0
+ self.china_mobile_init = 0
+ self.factory_status = 0
+ self.send_data_q = Queue(100)
+ self.ack_sem=0
+ _thread.start_new_thread(self.Socket_SEND_Thread,())
+ # 发数据线程
+ return None
+
+ def __socket_init(self):
+ # 创建一个socket实例
+ sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM, usocket.TCP_CUSTOMIZE_PORT)
+ sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1)
+ # 绑定IP
+ bind_addr = ('172.16.1.2', 5000)
+ sock.bind(bind_addr)
+ sock.settimeout(None)
+ return sock
+
+ def __socket_reinit(self):
+ return self.__socket_init()
+
+ def bootup_msg_to_bt(self):
+ modem_ver = modem.getDevFwVersion()
+ self.reply_cmd('0F',"BOOTUP@pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver))
+ self.reply_cmd('0F',"VOLUME:{}".format(voiceCall.getVolume()))
+
+ def btmcu_cmd_handler(self,cmd,parm):
+
+ # cmd = ""
+ # cmd_tmp= int(cmd_data)#将十进制数转换成int 再转换成十六进制
+ # cell_data = hex(cmd_tmp)
+ # decimal_number = int(cell_data, 16)
+ # cmd = "%02x"%(decimal_number) # 使用两位表示,不足前面补0
+ clog.info(cmd) # 输出: 07
+ clog.info("btmcu_cmd_handler cmd {0} , args {1}".format(cmd,parm))
+ if cmd == "00":
+ clog.info(cmd)
+ # UDP_CMD_GET_CAT1VER
+ modem_ver = modem.getDevFwVersion()
+ self.reply_cmd('00',"pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver))
+ elif cmd == "01":
+ # UDP_CMD_DIAL_NUMB
+ if eventMesh.publish("get_volte_switch") == 1: #只有BLE开了VOLTE才允许打电话
+ ret = voiceCall.callStart(str(parm))
+ # if ret != 0:
+ # ret = voiceCall.callStart(str(parm))
+ clog.info("ret={} {} {}".format(ret,cmd,parm))
+ if ret != 0:
+ self.reply_cmd('0F',"callcmd_fail")
+ else:
+ self.reply_cmd('0F',"callcmd_success")
+ else:
+ print("get_volte_switch NO")
+ self.reply_cmd('0F',"callcmd_fail")
+ elif cmd == "02":
+ clog.info(cmd)
+ # UDP_CMD_HUNGUP
+ ret = voiceCall.callEnd()
+ if ret != 0:
+ ret = voiceCall.callEnd()
+ if ret != 0:
+ self.reply_cmd('0F',"callend_fail")
+ else:
+ self.reply_cmd('0F',"callend_success")
+ elif cmd == "03":
+ clog.info(cmd)
+ # UDP_CMD_ANSWER
+ ret = voiceCall.callAnswer()
+ if ret != 0:
+ ret = voiceCall.callAnswer()
+ if ret != 0:
+ self.reply_cmd('0F',"callanswer_fail")
+ else:
+ self.reply_cmd('0F',"callanswer_success")
+ elif cmd == "04":
+ clog.info(cmd)
+ elif cmd == "05":
+ clog.info(cmd)
+ # UDP_CMD_SEND_SMS
+ elif cmd == "06":
+ clog.info(cmd)
+ # UDP_CMD_GET_TIME
+ time=utime.localtime()
+ zone=utime.getTimeZone()
+ #(2024, 3, 2, 18, 31, 32, 5, 62),8
+ # 返回当前时间戳,参数为元组
+ # timestamp = utime.mktime(time)
+ # clog.info(timestamp)
+ self.reply_cmd('06',"{0}@{1}".format(time,zone))
+ elif cmd == "07":
+ clog.info("cmd ==== 07!")
+ # UDP_CMD_GET_RECV_NETWORKSTAT
+ simstat = sim.getStatus()
+ imei = modem.getDevImei()
+ netstat = "0,10,0,10"
+ netstat_ = net.getState()
+ if netstat_ != -1 :
+ netstat = "{},{},{},{}".format(netstat_[0][0],netstat_[0][3],netstat_[1][0],netstat_[1][3])
+ # ([voice_state, voice_lac, voice_cid, voice_rat, voice_reject_cause, voice_psc], [data_state, data_lac, data_cid, data_rat, data_reject_cause, data_psc])
+ operator = net.operatorName()
+ signal = net.csqQueryPoll()
+ clog.info("imei:{0},sim:{1},oper:{2},signal:{3},net:{4}".format(imei,simstat,operator,signal,netstat))
+ self.reply_cmd('07',"imei:{0}@sim:{1}@oper:{2}@signal:{3}@net:{4}".format(imei,simstat,operator,signal,netstat))
+ elif cmd == "09":
+ clog.info("{},{}".format(cmd,parm))
+ # UDP_CMD_ATCMD
+ # net.setModemFun(0)
+ # net.setModemFun(1)
+ resp=bytearray(50)
+ ret=atcmd.sendSync("{}\r\n".format(parm),resp,'',10)
+ if ret == 0:
+ clog.info("reply:{},ret:{}".format(resp.decode(),ret))
+ self.reply_cmd('09',"{}".format(resp.decode()))
+ else:
+ clog.info("cmd error ret:{}".format(ret))
+ self.reply_cmd('09',"{}".format("at error"))
+
+ elif cmd == "10" or cmd == "12" or cmd == "14": #获取固件版本号或者获取BT保存的SIM卡的ICCID BLE那边是否开启电信入库功能
+ if 1: #CHINA_TELECOM_DM_FUN_ENABLE == 1 :
+ if eventMesh.publish("get_dmp_change_mode") == 1:
+ self.telecom_recv_cmd(cmd,parm)
+ else:
+ pass
+
+ if 1:#CHINA_MOBILE_DM_FUN_ENABLE == 1:
+ if eventMesh.publish("get_dmp_change_mode") > 1:
+ self.china_mobile_recv_cmd(cmd,parm)
+ else:
+ pass
+ pass
+ elif cmd == "13":
+ on = int(parm)
+ clog.info("set_dmp_change_mode on:{}".format(on))
+ eventMesh.publish("set_dmp_change_mode",on)
+
+ elif cmd == "16":
+ if 1: #CHINA_MOBILE_DM_FUN_ENABLE == 1:
+ if eventMesh.publish("get_dmp_change_mode") > 1:
+ self.china_mobile_recv_cmd(cmd,parm)
+ else:
+ pass
+ elif cmd == "17": #用于CAT1恢复出厂需要清空数据的标识通用
+ eventMesh.publish("set_factory_status",int(parm))
+ elif cmd == "18":
+ eventMesh.publish("set_dmp_cm_address",str(parm))
+ elif cmd == "19": #DTMF功能
+ voiceCall.startDtmf(str(parm),100) #100ms 持续时间 100-1000
+ elif cmd == "1A":
+ eventMesh.publish("set_volte_switch",int(parm))
+ elif cmd == "1B":
+ print("fota {}".format(str(parm).split("and")[0]))
+ print("fota {}".format(str(parm).split("and")[-1]))
+ # httpota = httpota()
+ httpota.run( str(parm).split("and")[0], str(parm).split("and")[-1])
+ # eventMesh.publish("set_volte_switch",int(parm))
+ # UDP_MSG_OTA
+ elif cmd == "AC":#
+ if self.ack_sem==1:
+ self.ack_sem=0
+
+ def telecom_recv_cmd(self,cmd,parm):
+ if cmd == "10":
+ self.software_version = str(parm)
+ eventMesh.publish("set_dev_version",self.software_version)
+ clog.info("software_version:{},{}".format(self.software_version,parm))
+ elif cmd == "12":
+ pass
+ elif cmd == "14":#
+ pass
+ pass
+
+ def set_volte_switch(self,event,msg): #设置VOLTE开关
+ self.volte_switch = int(msg)
+
+
+ def get_volte_switch(self,event,msg): #获取VOLTE开关
+
+ return self.volte_switch
+
+
+ def china_mobile_recv_cmd(self,cmd,parm): #移动入库相关指令
+ if cmd == "10":
+ self.software_version = str(parm)
+ eventMesh.publish("set_dev_version",self.software_version)
+ clog.info("software_version:{},{}".format(self.software_version,parm))
+ elif cmd == "16": #获取BLE mac地址
+ eventMesh.publish("set_dev_mac",str(parm))
+ clog.info("parm:{}\r\n".format(parm))
+
+ pass
+ def get_factory_status(self,event,msg):
+ return self.factory_status
+ def set_factory_status(self,event,msg):
+ self.factory_status = int(msg)
+ if self.factory_status == 0: #只有为的时候才设置进去 1不再设置
+ self.reply_cmd('17',"{}".format(1))
+
+ def send_dmp_cm_address_toBLE(self,event,msg):
+ buf_tmp = "address:"+str(msg)
+ self.reply_cmd('18',"{}".format(buf_tmp))
+
+ def set_dmp_change_mode(self,event,msg):
+ self.telecom_dmp_switch = msg
+ def delete_sms_single_data(self,event,msg): #删除单条信息
+ sms.deleteMsg(int(msg))
+
+ def get_dmp_change_mode(self,event,msg):
+ return self.telecom_dmp_switch
+ def delete_sms_event(self,event,msg):
+ self.deletSmsTimer.start(2*1000,0,self.delete_sms_cb)
+ def delete_sms_cb(self,*argc):
+ eventMesh.publish_async("remove_all_sms_cb","",1*1024)
+ def remove_all_sms_cb(self, event, msg):
+ clog.info("remove_all_sms_cb\r\n")
+ msg_nums = sms.getMsgNums() #短信数量
+ if msg_nums == -1:
+ msg_nums = 0
+ sms_data = sms.getSaveLoc()
+ clog.info("{}\r\n".format(sms_data))
+ if sms_data == -1:
+ return
+ sms_max = sms_data[0][2] #最大存储短信数量
+ if sms_max >= msg_nums and sms_max > 0:
+ sms.deleteMsg(1,4) #删除所有的sms信息
+
+ def send_singal_data_toBle(self,event,msg):
+ msg_nums = sms.getMsgNums() #短信数量
+ if msg_nums == -1:
+ msg_nums = 0
+ sms_data = sms.getSaveLoc()
+ if sms_data == -1:
+ return
+ sms_max = sms_data[0][2] #最大存储短信数量
+ clog.info("recv:{}".format(int(msg)))
+ message=self.sms_get_message_info(int(msg))
+ if message == -1: #说明没有这条短信
+ return
+ message_pdu = sms.decodePdu(message[5],20)
+
+ if message_pdu != -1: #解码出来的内容
+
+ message_ref = message[0] #编码
+ message_total_num = message[1] #总共条数
+ message_seq = message[2] #当前第几条
+ data = message[5] #内容
+ data_len = len(data) #内容长度
+ # ref :短信参考标识,同一个标识表明为同一条短信
+ # total_num :此条长短信总条数 大于1属于长短信
+ # seq :此条短信在长短信中的序号
+ # print("message:{} {}\r\n".format(message,message_pdu))
+ msg_total = "ref:"+str(message_ref)+"@total_num:"+str(message_total_num)+"@seq:"+str(message_seq)+"@data:"+str(message[5])
+ self.reply_cmd('15',msg_total)
+
+ eventMesh.publish("delete_sms_single_data",int(msg))
+
+ def sms_deal_phone_number(self,args):
+ data=enumerate(args)
+ data_str1=""
+ data_str2=""
+ data_str3=""
+ for index,value in data:
+ if index % 2 == 0:
+ data_str1=data_str1+value
+ else:
+ data_str2=data_str2+value
+ for i in range(0,len(data_str1)):
+ data_str3=data_str3+data_str2[i]
+ data_str3=data_str3+data_str1[i]
+ return data_str3
+ def sms_get_message_info(self,index):
+ """
+ :param index :短信索引值
+ :tyoe index :整形
+
+ :return :元组类型
+ 元组内容:
+ (message_ref,message_total_num,message_seq,sub_message_data,pdu_tye,sub_message_len)
+
+ :message_ref :短信参考标识,同一个标识表明为同一条短信
+ :message_total_num :此条长短信总条数
+ :message_seq :此条短信在长短信中的序号
+ :sub_message_data :词条短信的内容
+ :pdu_tye :PDU类型,bit 6标记是否包含用户报文头,长短信需要
+ :sub_message_len :此条短信内容长度
+
+ """
+
+ message0=sms.searchPduMsg(index)
+ #print("sms_get_message_info:message0:{}".format(message0))
+ if message0 == -1:
+ return -1
+
+ sca_num = int(message0[0:2],16) - 1
+ data_len = 2
+ addr_type= message0[data_len:data_len+1*2]
+ data_len = data_len+1*2
+
+ sca = message0[data_len:data_len+sca_num*2]
+ # 电话号码高低位需要转换
+ sca = self.sms_deal_phone_number(sca)
+
+ # if sca_num % 2 == 1:
+ # print("Get SCA phone {}".format(sca[:-1]))
+ # else:
+ # print("Get SCA phone {}".format(sca))
+
+ data_len = data_len+sca_num*2
+
+ pdu_tye = int(message0[data_len:data_len+1*2],16)
+ data_len = data_len+1*2
+
+ oa_num = int(message0[data_len:data_len+1*2],16)
+ data_len = data_len+1*2
+ oa_addr_type = message0[data_len:data_len+1*2]
+ data_len = data_len+1*2
+
+ if oa_num % 2 == 1:
+ oa_num_t = int((oa_num + 1)/2)
+ else:
+ oa_num_t = int((oa_num )/2)
+
+ oa = message0[data_len:data_len+oa_num_t*2]
+ # 电话号码高低位需要转换
+ oa = self.sms_deal_phone_number(oa)
+
+ # if oa_num % 2 == 1:
+ # print("Get OA phone {}".format(oa[:-1]))
+ # else:
+ # print("get OA phone {}".format(oa))
+
+ data_len = data_len+oa_num_t*2
+ pid = message0[data_len:data_len+1*2]
+
+ data_len = data_len+1*2
+ dcs = message0[data_len:data_len+1*2]
+ data_len = data_len+1*2
+ scts = message0[data_len:data_len+7*2]
+ data_len = data_len+7*2
+ sub_message_len = int(message0[data_len:data_len+1*2],16)
+ data_len = data_len+1*2
+ sub_message_head = message0[data_len:data_len+6*2]
+ data_len = data_len+6*2
+
+ # 或短信用户数据
+ sub_message_data = message0[data_len:data_len+sub_message_len*2]
+
+ #长短信
+ if ((pdu_tye & 0x40 ) >> 6) == 1:
+ #长短信,处理长短信用户报文头
+ message_ref = int(sub_message_head[6:8],16)
+ message_total_num = int(sub_message_head[8:10],16)
+ message_seq = int(sub_message_head[10:12],16)
+ return [message_ref,message_total_num,message_seq,pdu_tye,sub_message_len,message0]
+ else:
+ # 短短信
+ return [0,1,1,pdu_tye,sub_message_len,message0]
+
+
+
+ def send_sms_max_to_Ble(self,event,msg):
+ msg_nums = sms.getMsgNums()#短信数量
+ if msg_nums == -1:
+ msg_nums = 0
+ sms_data = sms.getSaveLoc()
+ if sms_data != -1:
+ sms_max = sms_data[0][2]#最大存储短信数量
+ self.reply_cmd('15',"@sms_max:"+str(sms_max)+"@current_num:"+str(msg_nums))
+ pass
+
+ def get_all_sms_data(self,event,msg):
+ msg_total = ""
+ SMS_lis={}
+ SMS_lis_count = 0
+ sms_data = sms.getSaveLoc()
+ clog.info(sms_data)
+ if sms_data == -1:
+ return
+ sms_max = sms_data[0][2]#最大存储短信数量
+ clog.info(sms_max)
+ self.msg_nums = sms.getMsgNums()
+ if self.msg_nums_old != self.msg_nums:
+ self.send_data = []
+ self.msg_nums_old = self.msg_nums
+ if self.send_data == [] :
+ for i in range(self.msg_nums):
+ phonenum = ""
+ data =""
+ time = ""
+ data_len = 0
+ message=self.sms_get_message_info(self.msg_nums-i-1)
+ if message == -1:
+ break
+ data = message[5]
+ sms_data = []
+ code = message[0]#编码
+ num = message[1]#总共条数
+ curren_num = message[2]#当前第几条
+ data_len = message[4]
+ sms_data.append(code)#编码 编码相同是同一条短信的内容
+ sms_data.append(num)
+ sms_data.append(curren_num)
+ sms_data.append(data)
+ sms_data.append(data_len)
+ self.send_data.append(sms_data)
+ count = len(self.send_data)
+ for i in range(count):
+ text = self.send_data[i]
+ clog.info("text:{} {} {}\r\n".format(text[0],text[1],text[2]))
+
+ msg_total = "@code:"+str(text[0])+"@totalcodenum:"+str(text[1])+"@currcodeid:"+str(text[2])+"@data:"+str(text[3])
+ self.reply_cmd('17',msg_total)
+
+ # 来电提醒
+ def notifyIncomingcall(self, incomming_numb):
+ self.clear_remain()
+ __head = '0C'
+ __message = str(incomming_numb)
+ self.__Socket_UDP(__head, __message)
+ # if self.__err == 1 or self.__value[2] != 'OK':
+ # return -1
+ return 0
+
+ # 电话接听消息
+ def notifyConnecteCall(self, phone_numb):
+ self.clear_remain()
+ __head = '0A'
+ __message = str(phone_numb)
+ self.__Socket_UDP(__head, __message)
+ # if self.__err == 1 or self.__value[2] != 'OK':
+ # return -1
+ return 0
+
+ # 电话拒接消息
+ def notifyDisconnectCall(self, phone_numb):
+ self.clear_remain()
+ __head = '0B'
+ __message = str(phone_numb)
+ self.__Socket_UDP(__head, __message)
+ # if self.__err == 1 or self.__value[2] != 'OK':
+ # return -1
+ return 0
+
+ def wait_network_ready(self):
+ if(self.__waiting_netstat == 1):
+ return 0
+ self.__waiting_netstat = 1
+ stage, state = checkNet.waitNetworkReady(30)
+ pm.wakelock_unlock(lpm_fd)
+ if stage == 3 and state == 1:
+ clog.info('Network connection successful.')
+ self.set_network_config()
+ self.__net_connected = 1
+ eventMesh.publish("set_network_state",self.__net_connected)
+ self.__waiting_netstat = 0
+ return 0
+ else:
+ clog.info('Network connection failed, stage={}, state={}'.format(stage, state))
+ self.reset_network_config()
+ self.__net_connected = 0
+ eventMesh.publish("set_network_state",self.__net_connected)
+
+ self.__waiting_netstat = 0
+ return -1
+
+ # 查询网卡状态
+ def timesync(self,_timesync):
+ self.clear_remain()
+ message = str(_timesync)
+ self.__Socket_UDP('0D', message)
+ return 0
+
+ def reply_timesync(self,_timesync):
+ self.clear_remain()
+ message = str(_timesync)
+ self.__Socket_UDP_noreply('0D', message)
+ return 0
+
+ def reply_cmd(self,cmd,_timesync):
+ try :
+ clog.info('reply_cmd 1')
+ self.clear_remain()
+ message = str(_timesync)
+ clog.info('reply_cmd 2')
+ self.__Socket_UDP_noreply(cmd, message)
+ except:
+ clog.info('reply_cmd')
+ return 0
+
+ def clear_remain(self):
+ # if self.__queue.empty() == False:
+ # self.__queue.get()
+ self.__err = 0
+ # self.__value = None
+ #添加路由信息
+ def router_add(self, ip='192.168.4.1', mask='255.255.255.0'):
+ self.ip = ip
+ self.mask = mask
+
+ return slip.router_add(self.ip, self.mask)
+
+ # 获取slip的网络配置
+ def ipconfig(self):
+ return slip.ipconfig()
+
+ # 设置dns服务器
+ def set_dns(self, pri_dns='8.8.8.8', sec_dns='114.114.114.114'):
+ self.pri_dns = pri_dns
+ self.sec_dns = sec_dns
+ return slip.set_dns(self.pri_dns,self.sec_dns)
+
+ # 设置默认网卡
+ def set_default_NIC(self, ip_str):
+ self.ip_str = ip_str
+ return slip.set_default_netif(self.ip_str)
+
+ def reset_network_config(self):
+ if (self.__net_connected == 0):
+ clog.info("skip reset_network_config")
+ return 0
+ Info = dataCall.getInfo(1,0)
+ clog.info("Info{}".format(Info))
+ default_NIC_ip = Info[2][2] # 假设默认网卡ip地址为10.10.1.1,请根据实际情况更改
+ segment_ip = '172.16.4.0' # 假设ap模式网段范围是[192.168.4.0 ~ 192.168.4.255],请根据实际情况更改
+ mask = '255.255.255.0' # 假设子网掩码为255.255.255.0,请根据实际情况更改
+ # 配置默认网卡,通过默认网卡进行网络转发
+ cat1service.set_default_NIC(default_NIC_ip)
+ clog.info("default_NIC_ip {0} segment_ip {1}".format(default_NIC_ip,segment_ip))
+ #添加路由规则,只有该网段IP才进行转发
+ cat1service.router_add(segment_ip, mask)
+
+ pri_dns = '8.8.8.8' # 假设DNS首选地址为8.8.8.8,请根据实际情况更改
+ sec_dns = '114.114.114.114' # 假设DNS备选地址为114.114.114.114,请根据实际情况更改
+ # 配置网卡DNS服务器
+ cat1service.set_dns(pri_dns, sec_dns)
+ # 网卡IP信息查询
+ cat1service.ipconfig()
+
+ def set_network_config(self):
+
+
+ if (self.__net_connected == 1) :
+ clog.info("skip set_network_config")
+ return 0
+ Info = dataCall.getInfo(1,0)
+ clog.info("Info{}".format(Info))
+ default_NIC_ip = Info[2][2] # 假设默认网卡ip地址为10.10.1.1,请根据实际情况更改
+ segment_ip = '172.16.1.0' # 假设ap模式网段范围是[192.168.4.0 ~ 192.168.4.255],请根据实际情况更改
+ mask = '255.255.255.0' # 假设子网掩码为255.255.255.0,请根据实际情况更改
+ # 配置默认网卡,通过默认网卡进行网络转发
+ cat1service.set_default_NIC(default_NIC_ip)
+ clog.info("default_NIC_ip {0} segment_ip {1}".format(default_NIC_ip,segment_ip))
+ #添加路由规则,只有该网段IP才进行转发
+ cat1service.router_add(segment_ip, mask)
+
+ pri_dns = '8.8.8.8' # 假设DNS首选地址为8.8.8.8,请根据实际情况更改
+ sec_dns = '114.114.114.114' # 假设DNS备选地址为114.114.114.114,请根据实际情况更改
+ # 配置网卡DNS服务器
+ cat1service.set_dns(pri_dns, sec_dns)
+ # 网卡IP信息查询
+ cat1service.ipconfig()
+ if eventMesh.publish("get_dmp_change_mode") == 0:#入库功能关闭
+ return
+ if 1: #CHINA_TELECOM_DM_FUN_ENABLE == 1:#电信入库功能 不使用设置 0 防止两边不同步修改
+ if eventMesh.publish("get_dmp_change_mode") == 1:
+ eventMesh.publish("set_network_state",1)
+ # telecomDmpCb.telecom_dmp_power_on_init()
+ if 1: #CHINA_MOBILE_DM_FUN_ENABLE == 1:
+ if eventMesh.publish("get_dmp_change_mode") == 2:
+ eventMesh.publish("set_network_state",1)
+ if self.china_mobile_init == 1:
+ return
+ self.china_mobile_init = 1
+ #移动入库的初始化
+ # chinamobileCb.china_mobile_init()
+ if eventMesh.publish("get_dmp_change_mode") == 3:
+ if self.china_mobile_ai_init == 1:
+ return
+ self.china_mobile_ai_init = 1
+ eventMesh.publish("set_network_state",1)
+ aiRegulation.AIRegulation_init()
+
+ def cat1_reply_iccid_to_ble(self,event,msg):
+ ICCID_DATA = str("ICCID:")+str(msg)
+ self.reply_cmd('11',"{}".format(ICCID_DATA))
+ pass
+ def cat1_reply_timesec_to_ble(self,event,msg):
+
+ self.reply_cmd('14',"REGIST_TIME:{}".format(msg))
+ pass
+ # 释放slip网卡
+ def stop(self):
+ slip.destroy()
+ return 0
+
+
+ # 封装tlv数据包
+ def __pack_tlv_format(self, head, content):
+ # self.head = head
+ # self.content = content
+ if len(content) == 0 or len(content) > 9999 or len(head) != 2:
+ clog.error('illegal pack tlv content')
+ return -1
+ len_str ='%04d' % len(content)
+ tlv_pack = CAT1_SERVICE_HEAD+head+len_str+content
+ return tlv_pack
+ # 解码tlv数据包
+ def __unpack_tlv_format(self, msg):
+ clog.info('__unpack_tlv_format {}\r\n'.format(msg))
+ self.msg = str(msg)[2:]#这是去除head FE
+ tag = self.msg[0:2]
+ length = self.msg[2:6]
+ value = self.msg[6:]
+ len_str ='%04d' % len(value)
+ if len(value) == 0 or len(value) > 9999 or len(tag) != 2 or len_str != self.msg[2:6]:
+ clog.error('__unpack_tlv_format err')
+ return -1
+ clog.info('__unpack_tlv_format: {} {} {}\r\n'.format(tag,length,value))
+ unpack = (tag,length,value)
+ return unpack
+ # socket通信(UDP)模块
+ def __Socket_UDP(self, head, content):
+ # 0 则 __Socket_UDP_write
+ self.send_data_q.put([head,content])
+ def Socket_SEND_Thread(self):
+ while True:
+ try:
+ clog.info("send====")
+ data=self.send_data_q.get()
+ self.ack_sem=1
+ # # if data[2]:
+ # self.__Socket_UDP_noreply_write( data[0], data[1])
+ # else :
+ self.__Socket_UDP_write( data[0], data[1])
+
+
+ clog.info("Socket_SEND_Thread data:{} {}".format(data[0],data[1]))
+ count=20
+
+ while count & self.ack_sem :
+ utime.sleep_ms(1)
+ count=count-1
+ # if data[2]:
+ # self.__Socket_UDP_noreply_write( data[0], data[1])
+ # else :
+ self.__Socket_UDP_write( data[0], data[1])
+
+ clog.info("Socket_SEND_Thread while data:{} {}".format(data[0],data[1]))
+
+ if data:
+ clog.info("data ok!!")
+ else:
+ clog.error("data error!!")
+ except Exception :
+ clog.error("sned Socket >>>")
+
+ def __Socket_UDP_write(self, head, content):
+ try:
+ ##self.head = head
+ # self.content = content
+ gpioWakeBT.write(1)
+ utime.sleep_ms(2)
+ gpioWakeBT.write(0)
+ utime.sleep_ms(20)
+ # 消息处理
+ msg = self.__pack_tlv_format(head, content)
+
+ # 向服务端发送消息
+ server_addr = ('172.16.1.5',1000)
+ clog.info("__Socket_UDP send msg {}".format(msg))
+ self.__err = 0
+ self.__sock.sendto(msg,server_addr)
+ clog.info("__Socket_UDP send 2")
+ self.__wait_resp = 1
+ # data = self.__queue.get()
+ self.__wait_resp = 0
+ # return data
+ return 1
+ except Exception as error:
+ clog.error(error)
+ return 0
+
+ def __Socket_UDP_noreply(self, head, content):
+ # 1 则 __Socket_UDP_noreply_write
+ self.send_data_q.put([head,content])
+
+ def __Socket_UDP_noreply_write(self, head, content):
+ # self.head = head
+ # self.content = content
+ gpioWakeBT.write(1)
+ utime.sleep_ms(2)
+ gpioWakeBT.write(0)
+ utime.sleep_ms(20)
+ # 消息处理
+ msg = self.__pack_tlv_format(head, content)
+
+ # 向服务端发送消息
+ server_addr = ('172.16.1.5',1000)
+
+ clog.info("__Socket_UDP_noreply send msg {}".format(msg))
+ self.__err = 0
+ data_size = self.__sock.sendto(msg,server_addr)
+ clog.info("self.__sock data_size {}".format(data_size))
+ self.__wait_resp = 0
+ return 0
+
+ # socket通信(UDP)模块
+ def __Socket_Thread(self):
+ while True:
+ try:
+ clog.info("recv====")
+ data=self.__sock.recv(1024)
+ clog.info("data:{}".format(data))
+ if data:
+ value = self.__unpack_tlv_format(data.decode())
+ if value != -1:
+ clog.info('mode: {0}, recv {1} bytes, Data: {2}'.format (value[0],len(data), value[2]))
+ if value[1] == 'FF':
+ self.btmcu_cmd_handler(value[0],value[2])
+ else:
+ # self.__value = value
+ # self.__queue.put('1')
+ self.btmcu_cmd_handler(value[0],value[2])
+ clog.info("End else Thread")
+ else:
+ clog.error("data error!!")
+ except Exception as recverr:
+ clog.error("recverr:{}\r\n".format(recverr))
+ if "110" in str(recverr):
+ self.__err = 1
+ # if self.__wait_resp == 1:
+ # self.__queue.put('0')
+ else:
+ utime.sleep(1)
+ self.__sock = self.__socket_reinit()
+
+
+
+ clog.info("End Socket Thread")
+
+
+
+
+# UDP_CMD_GET_CAT1VER = '0', // 获取 Cat1 版本号
+# UDP_CMD_DIAL_NUMB = '1', // 拨打电话
+# UDP_CMD_HUNGUP = '2', // 挂断电话
+# UDP_CMD_ANSWER = '3', // 接听电话
+# UDP_CMD_CAT1_OTA_UPDATE = '4', // 触发Cat1 OTA升级,mcu提供url
+# UDP_CMD_SEND_SMS = '5', // 发送SMS短信,mcu提供电话号及短信内容
+# UDP_CMD_GET_TIME = '6', // 获取Cat1 时间 ,YYYYMMDD HHmmss zone
+# UDP_CMD_GET_NETWORKSTAT = '7', //获取Cat1 信号信息,VOLTE信息,信号强度,SIM卡状态
+# 下文进行系统配置
+clog.info("Cat1Service start")
+
+cat1service = Cat1Service()
+
+#send_data_q = Queue(100)
+
+#voice call callback function
+def voice_callback(args):
+ if args[0] == 10:
+ if eventMesh.publish("get_volte_switch") == 0: #关闭VOLTE功能
+ clog.info('voicecall auto end:')
+ voiceCall.callEnd()
+ else:
+ # gpioWakeBT.write(1)
+ cat1service.notifyIncomingcall(args[6])
+ elif args[0] == 11:
+ if eventMesh.publish("get_volte_switch") == 1: #开启VOLTE功能
+ clog.info('voicecall connected, PhoneNO: \n'.format(args[6]))
+ cat1service.notifyConnecteCall(args[6])
+ elif args[0] == 12:
+ clog.info('voicecall disconnect')
+ if eventMesh.publish("get_volte_switch") == 1: #开启VOLTE功能
+ clog.info('voicecall disconnected, PhoneNO: \n'.format(args[6]))
+ cat1service.notifyDisconnectCall(args[6])
+ elif args[0] == 13:
+ clog.info('voicecall is waiting, PhoneNO: \n'.format(args[6]))
+ elif args[0] == 14:
+ clog.info('voicecall dialing, PhoneNO: \n'.format(args[6]))
+ elif args[0] == 15:
+ clog.info('voicecall alerting, PhoneNO: \n'.format(args[6]))
+ elif args[0] == 16:
+ clog.info('voicecall holding, PhoneNO: \n'.format(args[6]))
+ else:
+ clog.info('voice_callback , args[0]: \n'.format(args[6]))
+
+#电话消息反馈
+voiceCall.setCallback(voice_callback)
+
+
+def checknet_cb(arg):
+ clog.info("start checktime!!")
+ # if 1: #CHINA_TELECOM_DM_FUN_ENABLE == 1:#这是手表每30s检查一次
+ # if eventMesh.publish("get_dmp_change_mode") == 1:
+ # telecomDmpCb.telecom_dmp_power_on_count()
+
+ _thread.start_new_thread(cat1service.wait_network_ready, ())
+ # time=utime.localtime()
+ # zone=utime.getTimeZone()
+ #(2024, 3, 2, 18, 31, 32, 5, 62),8
+ # cat1service.timesync("{0},{1}".format(time,zone))
+# _thread.start_new_thread(cat1service.wait_network_ready, ())
+timer = osTimer()
+# checknet_cb(())
+timer.start(30000,1,checknet_cb)
+
+def bootupmsg_cb(arg):
+ cat1service.bootup_msg_to_bt()
+
+
+delaybootupmsg_timer = osTimer()
+delaybootupmsg_timer.start(1000,0,bootupmsg_cb)
+
+# def checkpin_cb(arg):
+# clog.info("recvDataPin={}".format(recvDataPin.read()))
+
+# timerCheckRevPin = osTimer()
+# timerCheckRevPin.start(1000,1,checkpin_cb)
+
+
+
+
+
+
+# while True:
+# utime.sleep(5)
+
+
+# uping.ping("172.16.1.5")
+ # 获取网卡当前工作状态
+
+# gpioWakeBT.write(1)
+# utime.sleep(1)
+
+# timesync = net.nitzTime()
+# cat1service.timesync(timesync)
+
+
+#url = "http://zzhc.vnet.cn:9998/"
+
+
--- /dev/null
+import app_fota
+from misc import Power
+import modem
+import ujson
+import request
+import ql_fs
+import checkNet
+import sys
+
+#远程升级
+
+import fota
+import utime
+import log
+import uos
+
+PROJECT_VERSION="PY_OTA_V14"
+CONFIG_JSON="/usr/system_config.json"
+CURRENT_APP_TYPE="pyota"
+# 设置日志输出级别
+log.basicConfig(level=log.INFO)
+fota_log = log.getLogger("Fota")
+
+
+def get_versionkeyname_by_py(app_type):
+ return str("{}version".format(app_type))
+
+def get_default_versionvalue_by_py(app_type):
+ if (app_type == "pyota"):
+ return "PY_OTA_V13"
+
+
+#如果没有configfile则创建它
+if not ql_fs.path_exists(CONFIG_JSON):
+ data = {str(get_versionkeyname_by_py(CURRENT_APP_TYPE)):get_default_versionvalue_by_py(CURRENT_APP_TYPE)}
+ try:
+ ql_fs.touch(CONFIG_JSON,data)
+ except Exception as e:
+ print("checkota 创建出错 {}".format(e))
+
+def set_version_to_json_config(app_type,keyvalue):
+ try:
+ config_data = ql_fs.read_json(CONFIG_JSON)
+ config_data.update( {str(get_versionkeyname_by_py(app_type)):keyvalue})
+
+ ql_fs.touch(CONFIG_JSON, config_data)
+ print("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue))
+ print("{}".format(config_data))
+ except Exception as e:
+ print("checkota 创建出错 {}".format(e))
+
+def get_version_from_json_config(app_type):
+ try:
+ config_data = ql_fs.read_json(CONFIG_JSON)
+ keyvalue = config_data.get( get_versionkeyname_by_py(app_type),get_default_versionvalue_by_py(app_type))
+ print("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue))
+ return keyvalue
+ except Exception as e:
+ print("get_version_from_json_config出错 {}".format(e))
+ return ""
+
+def result(args):
+ print('download status:',args[0],'download process:',args[1])
+
+def check_fota():
+ modem_ver = modem.getDevFwVersion()
+ imei = modem.getDevImei()
+ url = "http://icfota.snicker.com.cn:8089/fd230ota.jsp?product=FD230&pkgver={0}&imei={1}".format(modem_ver,imei)
+ response = request.get(url)
+ print(url)
+ data = response.json()
+ if(data['UptoDate'] == False):
+ print("Need update python application")
+ fota_obj = fota() # 创建Fota对象
+ print("httpDownload...")
+ srcurl = data['url']
+ #差分升级方式
+ # res = fota_obj.httpDownload(url1="http://www.example.com/fota.bin",callback=result)
+ # mini fota方式
+ print("{},{}".format("{}/dfota_1.bin".format(srcurl),"{}/dfota_2.bin".format(srcurl)))
+ res = fota_obj.httpDownload(url1="{}/dfota_1.bin".format(srcurl),url2="{}/dfota_2.bin".format(srcurl),callback=result)
+ #差分升级FTP方式
+ #res = fota_obj.httpDownload(url1="ftp://user:password@ip:port/fota.bin",callback=result) #其中user,password,ip,port需要填写具体使用的FTP服务器信息
+ if res != 0:
+ print("httpDownload error")
+ return
+ print("wait httpDownload update...")
+ else:
+ print("No need update python application")
+
+def do_app_update_internal(app_type):
+ fota = app_fota.new()
+ imei = modem.getDevImei()
+ pythonversion=get_version_from_json_config(app_type)
+ url = "http://icfota.snicker.com.cn:8089/fd230ota.jsp?product=FD230&pkgver={0}&imei={1}".format(pythonversion,imei)
+ try:
+ response = request.get(url)
+ print(url)
+ data = response.json()
+ if data['UptoDate'] == False:
+ print("Need update python application {}".format(data["appcount"]))
+ for app_update in data["apps"]:
+ srcurl = app_update['url']
+ print("run start...")
+ targetpyname = app_update['OtaPackageName']
+ version = app_update['OtaPackageVersion']
+ tmpfile_path = "/usr/.updater/{}".format(targetpyname)
+ targetfile_path = "/usr/{}".format(targetpyname)
+ print("download {0} to {1}".format(srcurl,targetfile_path))
+ if ql_fs.path_exists(tmpfile_path):
+ try:
+ uos.remove(tmpfile_path)
+ except Exception as e:
+ print("update remove出错 {}".format(e))
+ ret = fota.download(srcurl,targetpyname)
+ if ret == 0 :
+ try:
+ ql_fs.file_copy(targetfile_path, tmpfile_path)
+ set_version_to_json_config(app_type,version)
+ print("ota success")
+ if ql_fs.path_exists(tmpfile_path):
+ try:
+ uos.remove(tmpfile_path)
+ except Exception as e:
+ print("update remove出错 {}".format(e))
+ except Exception as e:
+ print("ota failed!")
+ else:
+ print("ota failed")
+ # 升级后重启
+ Power.powerRestart()
+ else:
+ print("No need update python application")
+ except Exception as e:
+ print("nonetwork:{}".format(e))
+
+if __name__ == '__main__':
+ print("check ota start!!!!!!!!!!")
+ set_version_to_json_config(CURRENT_APP_TYPE,PROJECT_VERSION)
+ stage, state = checkNet.waitNetworkReady(1)
+ if stage == 3 and state == 1:
+ print('Network connection successful.')
+ do_app_update_internal("pyota")
+ # check_fota()
+ else:
+ print('Network connection failed, stage={}, state={}'.format(stage, state))
+
+# res = uos.statvfs("/usr")
+# res = list(res)
+# print('总ext空间:{} MB,剩余空间:{} MB'.format((((res[0] * res[2]) / 1024 / 1024)),((res[0] * res[3]) / 1024 / 1024)))
\ No newline at end of file
--- /dev/null
+#AI 纳管对接文件
+import modem
+import request
+import utime
+import osTimer
+import ql_fs
+from machine import RTC
+from misc import Power
+import uos
+import ujson
+import urandom
+from usr.EventMesh import eventMesh
+HEARBEAT_REPORT_TIMER_CONFIG = 60*60*12#60*60*12 #心跳上报时间间隔12小时可更改做测试
+REALY_TIME_COUNT = 60*60# #开启1小时实时定时器
+HEART_REPORT_ERROR_TIMER = 60 #心率上报错误定时器检测 按照1分钟检查
+PRODUCTID = "1927646275585744898" #产品ID
+PRODUCTKEY = "iijgiGiTolCblSFE" #产品KEY 平台创建产品是生成的
+HEART_REPORT_ERR_MAX_NUM = 30 #连续上报错误次数最大值 30 网络异常或者哪里报错了 重启设备 可根据实际的用户的需求更改次数
+REPORT_MODE = 1 #上报方式 1 24小时内一定上报一次 2 12小时后上报一次
+class AIRegulation:
+ #定义全局变量
+ def __init__(self):
+ self.timerStart = osTimer()
+ self.timerStartReportHr = osTimer()
+ self.productId = PRODUCTID
+ self.productKey = PRODUCTKEY
+ self.deviceId = "" #设备ID
+ self.deviceSecret = "" #设备私钥
+ self.config_data = {}
+ self.getDevInforErrCount = 0 #获取设备信息错误次数累计
+ self.report_state = 0 #超过24小时清0
+ self.TimeSec = 0 #上报的时间戳
+ self.startTimerState = 0
+ self.software_version = ""
+ self.imei_new = ""
+ self.init_flag = 0
+ self.net_work_state = 0
+ self.dev_mac = ""
+ eventMesh.subscribe("get_dev_version",self.get_dev_version)
+ eventMesh.subscribe("set_dev_version",self.set_dev_version)
+ eventMesh.subscribe("get_dev_mac",self.get_dev_mac)
+ eventMesh.subscribe("set_dev_mac",self.set_dev_mac)
+ eventMesh.subscribe("get_network_state",self.get_network_state)#订阅消息
+ eventMesh.subscribe("set_network_state",self.set_network_state)#订阅消息
+ self.report_err_count = 0 #上报错误次数 30次
+
+ def set_network_state(self,event,msg):
+ self.net_work_state=int(msg)
+
+ def get_network_state(self,event,msg):
+ return self.net_work_state
+
+ def set_dev_version(self,event,msg):
+ self.software_version=str(msg)
+
+ def get_dev_version(self,event,msg):
+ return self.software_version
+ def get_dev_mac(self,event,msg):
+ return self.dev_mac
+ def set_dev_mac(self,event,msg):
+ self.dev_mac = str(msg)
+ #要或者设备的mac 和设备的固件版本号
+
+ #读取存储设备的设备参数 包含设备imei 设备ID和设备私钥 同一个设备设备ID和设备私钥不变
+ def read_dev_storage_param(self):
+
+ IMEI = modem.getDevImei() #获取IMEI号
+ result_ok = 0 #返回结果状态
+ IFEXIST = ql_fs.path_exists("/usr/cm_ai_regulation.json") #
+ if IFEXIST == True: #文件存在
+ fileSize = ql_fs.path_getsize('usr/cm_ai_regulation.json')
+ if fileSize == 0:
+ result_ok = 0
+ print("设备信息配置文件不存在\r\n")
+ return result_ok
+ else:
+ try:
+ with open("/usr/cm_ai_regulation.json","r",encoding='utf-8') as fd:
+ try:
+ self.config_data = ujson.load(fd) #转换成json格式
+ if len(self.config_data) != 0:
+ if "deviceId" in self.config_data:#
+ self.deviceId = str(self.config_data["deviceId"]) #设备ID
+
+ #存在
+ if "deviceSecret" in self.config_data:
+ self.deviceSecret = str(self.config_data["deviceSecret"])
+ #存在
+ if "TimeSec" in self.config_data:
+ self.TimeSec = self.config_data["TimeSec"]
+ if "IMEI" in self.config_data:
+ self.imei_new = self.config_data["IMEI"]
+ if str(self.imei_new) != str(IMEI): #设备IMEI不一样也要重新获取
+ self.config_data["IMEI"] = str(IMEI)
+ self.write_config_msg_file(self.config_data)
+ result_ok = 0
+ return result_ok
+
+ if len(str(self.deviceId)) != 0 or len(str(self.deviceSecret)) != 0:
+ result_ok = 1
+ else: #m没有存储数据 需要从平台上获取设备信息
+ result_ok = 0
+ except Exception as error:
+ print("配置文件的内容不是json格式 保存数据的时候格式不对\r\n")
+ result_ok = 0
+ except Exception as error:
+ print("打开配置文件失败\r\n")
+ result_ok = 0
+ else:
+ print("配置文件不存在!!!!\r\n")
+ result_ok = 0
+
+ print("cm_ai_regulation result_ok: {} self.config_data:{}\r\n".format(result_ok,self.config_data))
+ return result_ok
+ #写文件信息
+ def write_config_msg_file(self,msg):
+
+ print("cm_ai_regulation msg:{}\r\n".format(msg))
+ with open("/usr/cm_ai_regulation.json",'w+',encoding="utf-8") as fd:
+ ujson.dump(msg,fd)
+ def get_dev_info(self): #是否需要获取设备信息
+ request_result = 0
+ netWorkState = eventMesh.publish("get_network_state")
+ if netWorkState == 0: #网络异常
+ request_result = 0
+ return request_result
+ url = "https://ivs.chinamobiledevice.com:11443/v2/customer/device/secret/info"
+ #获取设备ID和设备私钥
+ get_dev_storage = self.read_dev_storage_param() #返回1说明已经获取过设备信息 不需要再重新获取了只有
+ if get_dev_storage == 0: #还没有获取设备信息需要获取一遍
+ #获取设备设备信息地址
+ IMEI = modem.getDevImei() #获取IMEI号
+
+ headers_T ={"Content-Type":"application/json"}
+ config_data ={
+ "deviceNoType":"IMEI",
+ "deviceNo":str(IMEI),
+ "productKey":str(self.productKey),
+ "productId":str(self.productId),
+ }
+ print("ujson.dumps(config_data):{}".format(ujson.dumps(config_data)))
+
+ result_json = ""
+ response = 0
+ try:
+ response = request.post(url, data=ujson.dumps(config_data),headers =headers_T)
+ if response.status_code == 200: #服务器响应成功并返回数据
+ try:
+ content = response.content
+ c = next(content)
+ result_json = ujson.loads(c)
+ print("response.json:{}".format(ujson.loads(c)))
+ code = ""
+ message = ""
+ success = False
+ if "code" in result_json:
+ code = result_json["code"]
+ if "message" in result_json:
+ message = result_json["message"]
+ if "success" in result_json:
+ success = result_json["success"]
+ if code == "200" and message == "成功" and success == True:
+ if "data" in result_json:
+ data_json = result_json["data"]
+ if "deviceId" in data_json:
+ self.deviceId = data_json["deviceId"]
+ if "deviceSecret" in data_json:
+ self.deviceSecret = data_json["deviceSecret"]
+
+ if len(self.deviceId) != 0 or len(self.deviceSecret) != 0: #获取设备信息成功 保存数据 用做心跳上报
+ request_result = 1
+ self.config_data["deviceId"] = str(self.deviceId)
+ self.config_data["deviceSecret"] = str(self.deviceSecret)
+ IMEI = modem.getDevImei() #获取IMEI号
+ self.config_data["IMEI"] = str(IMEI)
+ self.write_config_msg_file(self.config_data)
+ # {
+ # "code":"200",
+ # "message":"成功",
+ # "success": true,
+ # "data":{
+ # "deviceId":"xxx",
+ # "deviceNo":"xxx",
+ # "productId":"xxx",
+ # "deviceSecret":"xxx"
+ # }
+ # }
+ else:
+ request_result = 0
+ print("后台返回数据json字段里面没有data字段\r\n")
+ else:
+ request_result = 0
+ print("后台返回数据失败 可能是设备没有加入产品或者产品私钥或者产品ID对不上\r\n")
+ except Exception as e: #不是json格式
+ print("not json data:{}".format(e))
+ request_result = 0
+ else:
+ print("未响应 或者网络异常连接不上后台\r\n")
+ request_result = 0
+ except Exception as e:
+ print("response error:{}".format(e))
+ request_result = 0
+ else:
+ request_result = 1
+ return request_result
+
+ #上报心跳数据
+ def report_hr_data(self): #设备ID 设备私钥不为空才可以上报
+ result_s = 0
+ netWorkState = eventMesh.publish("get_network_state")
+ if netWorkState == 0: #网络异常
+ result_s = 0
+ return result_s
+ if len(str(self.deviceId)) != 0 and len(str(self.deviceSecret)) != 0:
+
+ #########################################################
+ # {
+ # "deviceId":"1927659130106658817",
+ # "deviceSecret":"xmvlRHbEaKPtCqHt",
+ # "productId":"1927646275585744898",
+ # "productKey":"iijgiGiTolCblSFE",
+ # "params": {
+ # "innerIp": [
+ # "127.0.0.1"
+ # ],
+ # "netSpeed": "0Mbps",
+ # "netType": "4G",
+ # "platform": "RTOS",
+ # "sdkVersion": "ai_http_1.0",
+ # "firmwareVersion": "0.0.5.2",
+ # "imei": "860132060564184",
+ # "cmei": "",
+ # "mac": ""
+ # }
+ # }
+ IMEI = modem.getDevImei() #获取IMEI号
+ tmp_mac = ""
+ if len(self.dev_mac) != 0:
+ tmp_mac = self.dev_mac.replace(':', '-') #将传过来的字符里面的:转换成-
+ #数据格式内容
+ data_json = {
+ "deviceId":str(self.deviceId), #设备ID
+ "deviceSecret":str(self.deviceSecret), #设备私钥
+ "productId":str(self.productId), #产品ID
+ "productKey":str(self.productKey), #产品私钥
+ "params": {
+ "innerIp": [
+ "127.0.0.1"
+ ],
+ "netSpeed": "0Mbps",
+ "netType": "4G",
+ "platform": "RTOS",
+ "sdkVersion": "ai_http_1.0",
+ "firmwareVersion":str(self.software_version), #设备固件版本号
+ "imei": str(IMEI), #设备IMEI号
+ "cmei": "",
+ "mac": str(tmp_mac) #设备MAC地址
+ }
+ }
+ url = "https://ivs.chinamobiledevice.com:11443/v2/customer/device/report" #post请求上报数据心跳地址
+ #获取设备ID和设备私钥
+ try:
+ headers_T ={"Content-Type":"application/json"} #应用是json格式
+ response = request.post(url, data=ujson.dumps(data_json),headers =headers_T) #post请求数据
+ if response.status_code == 200: #服务器响应成功并返回数据
+ try:
+ content = response.content
+ c = next(content)
+ result_json = ujson.loads(c) #将字符串转换成json格式
+ print("response.json:{}".format(result_json))
+ code = ""
+ message = ""
+ success = False
+ if "code" in result_json:
+ code = result_json["code"]
+ if "message" in result_json:
+ message = result_json["message"]
+ if "success" in result_json:
+ success = result_json["success"]
+ if code == "200" and message == "成功" and success == True: #上报成功返回
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp) #获取当前时间戳 用于下次时间判断上报心跳数据
+ print("date_tmp :{} time_tmp:{}\r\n".format(date_tmp,time_tmp))
+ self.report_state = 1 #表示上报成功 置标志1 12小时之内不清0 12小时之后再次上报清零
+ self.TimeSec = str(time_tmp)
+ self.config_data["TimeSec"] = str(time_tmp)
+ IMEI = modem.getDevImei() #获取IMEI号
+ self.config_data["IMEI"] = str(IMEI)
+ self.write_config_msg_file(self.config_data)
+ # {
+ # "code":"200",
+ # "message":"成功",
+ # "success": true,
+ # "data":{
+ # "deviceId":"xxx",
+ # "protocolTypeTime":"xxx"
+ # }
+ # }
+ result_s = 1
+ else:
+ result_s = 0
+ except Exception as e: #不是json格式
+ print("response:{}".format(e))
+ result_s = 0
+ else:
+ result_s = 0
+ except Exception as e:
+ print("response:{}".format(e))
+ result_s = 0
+ if REPORT_MODE == 1: #上报方式1
+ if result_s == 1: #当前上报数据成功 开启下一个上报心跳数据定时器
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)
+ random_integer = urandom.randint(-15, 15) #两个时间戳相减大于24小时啧清0
+ timerStart_init = HEARBEAT_REPORT_TIMER_CONFIG*1000+random_integer*1000*60
+ print("timerStart_init {} random_integer:{}\r\n".format(timerStart_init,random_integer))
+ self.timerStartReportHr.start(timerStart_init,0,self.timerStartReportHrCbOne)#重新开始 单次定时器
+ else: #上报方式2
+ if self.startTimerState == 0:
+ self.startTimerState = 1
+ self.open_report_start_timer()
+ else:
+ result_s = 2
+ self.AIRegulation_init() #重新初始化
+ return result_s
+ return result_s
+ def timerStartReportHrCbOne(self,*argc):
+ reportStatus = self.report_hr_data() #上报心跳数据接口函数
+ print("timerStartReportHrCbOne {}\r\n".format(reportStatus))
+ if reportStatus == 0: #当前上报失败 开启1分钟的定时器检测
+ self.timerStart.stop()
+ self.report_err_count = 0
+ self.timerStart.start(HEART_REPORT_ERROR_TIMER*1000,1,self.oneMinTimerStartCb)#重新开始
+ else:
+ self.timerStart.stop()
+
+ def oneMinTimerStartCb(self,*argc):
+ reportStatus = self.report_hr_data()
+ print("oneMinTimerStartCb {}\r\n".format(reportStatus))
+ if reportStatus != 0: #
+ self.timerStart.stop()
+ else:
+ self.report_err_count+=1
+ if self.report_err_count >= HEART_REPORT_ERR_MAX_NUM:
+ self.report_err_count = 0
+ self.timerStart.stop()
+ Power.powerRestart() #重启设备 可能网络异常或者哪里出错了
+
+ def timerStartReportHrCb(self,*argc): #上报心跳定时器回调
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)
+ random_integer = urandom.randint(-15, 15) #-15 - +15上报时间随机值分钟单位 *60*1000
+ data = RTC().datetime()
+ year = data[0]
+ month = data[1]
+ day = data[2]
+
+ if self.report_state == 1: #上报过一次 就等下一个12小时再上报一次
+ #当前时间大于上次记录时间加上12小时就上报一次
+ next_alarm_time = utime.localtime(int(self.TimeSec))
+ old_month = next_alarm_time[1]
+ old_day = next_alarm_time[2]
+ old_year = next_alarm_time[0]
+ # if 1:
+ # if old_year != year or old_month != month or old_day != day:
+ # self.report_state = 0
+ # self.report_hr_data()
+
+ # else:
+ if (time_tmp >= self.TimeSec + HEARBEAT_REPORT_TIMER_CONFIG*1000 + random_integer*60*1000) or (old_year != year or old_month != month or old_day != day): #or old_year != year or old_month != month or old_day != day: #上次上报时间戳+12小时时间戳 大于当前时间戳 上报一次 或者年 月 日不一致也上报一次
+ self.report_state = 0
+ self.report_hr_data()
+ else: #确保12小时之内上报一次 每一个小时上
+ self.report_hr_data()#上报一次心跳数据
+
+ def open_report_start_timer(self): #1小时的定时器
+ self.timerStartReportHr.start(REALY_TIME_COUNT*1000,1,self.timerStartReportHrCb)#1小时定时
+
+ def timerStartCb(self,*argc):#获取设备信息定时器回调
+ getDevInfoState = self.get_dev_info()
+ if getDevInfoState == 0:#
+ self.getDevInforErrCount+=1
+ if self.getDevInforErrCount >= 20:
+ self.getDevInforErrCount = 0
+ self.timerStart.stop()
+ else:
+ self.getDevInforErrCount = 0
+ self.timerStart.stop()
+ self.report_hr_data()#上报一次心跳数据
+
+ def AIRegulation_init(self):#AI 纳管 初始化 获取完设备数据后立马上报心跳数据
+ status = eventMesh.publish("get_factory_status")
+ if status == None:
+ status = 0
+ print("get_factory_status:{}\r\n".format(status))
+ if status == 0:#恢复出厂或者新的机器需要清空不必要的数据
+ if self.init_flag == 0:#只初始化一次
+ IFEXIST = ql_fs.path_exists("/usr/cm_ai_regulation.json")
+ if IFEXIST == True:
+ uos.remove("/usr/cm_ai_regulation.json")
+ self.init_flag = 1
+ self.report_state = 0
+ self.getDevInforErrCount = 0
+ self.report_err_count = 0
+ self.timerStartReportHr.stop()
+
+ self.startTimerState = 0
+ getDevInfoState = self.get_dev_info()
+ if getDevInfoState == 0:#开机获取失败了再等30s重新获取 获取二十次都失败就等下次重启设备获取
+ self.timerStart.stop()
+ self.timerStart.start(30*1000,1,self.timerStartCb)#重新开始 开机10分钟内没有获取到设备信息就不获取了需要手动重启设备
+ else: #设备开机获取设备信息成功 立马上报一次心跳数据
+ self.report_hr_data()#上报一次心跳数据
+
+aiRegulation = AIRegulation()
+
--- /dev/null
+import app_fota
+from misc import Power
+import modem
+import ujson
+import request
+import ql_fs
+import checkNet
+import sys
+import sim
+
+from queue import Queue
+import usys
+import _thread
+import fota
+import utime
+import log
+import uos
+import osTimer
+import net
+import ql_fs
+from ucryptolib import aes
+import hashlib
+from usr.EventMesh import eventMesh
+# 设置日志输出级别
+log.basicConfig(level=log.INFO)
+fota_log = log.getLogger("china_mobile")
+import modem
+import base64
+import request
+import ujson
+BLOCK_SIZE = 16
+NEED_SAVE_CONFIG_FILE = 0 #是否需要保存上报次数 异常重试次数 时间戳到配置文件 0不保存 1保存
+#中国移动入库
+class chinamobile:
+ def __init__(self):
+ self.multiDayResend_timer = osTimer()#12小时定时器 多日重发的机制
+
+ self.multimer_count = 0#多日重发机制周期Count
+ self.multimer_init = 0
+ self.power_on_multiflag = 0
+ self.timer_count = 0
+ self.timerPowerNum = 0
+ self.telecom_init_state = 0#初始化状态开机检查标识
+ self.isRegistOk = 0#注册成功
+ self.config_data = {}
+
+ self.__net_connected = 0
+ self.regist_timeSec = 0
+ self.iccid_data = ""
+ self.software_version = ""
+ self.mac_data =""
+ self.address = "a.fxltsbl.com"
+
+ self.new_address = "a.fxltsbl.com"
+
+ self.retryInterval = 10
+ self.retryNum = 1#异常重试最大次数
+ self.heartBeatTime = 1440#心跳上报频率 单位分钟
+ self.reportTime = 1440#最大上报频率 自注册+心跳上报的频率次数不能大于最大上报频率次数
+ self.reportNum = 8 #最大上报次数
+
+
+ self.reportTime_Sec = 0 #保存本地 保存时间戳下一次开机使用
+ self.report_Num_old = 0#保存本地
+ self.retryNum_old = 0#保存本地
+ self.init_flag = 0#初始化状态指初始化一次
+ self.retryTimer = osTimer()#异常重试定时器
+ self.retpoertTimerC = osTimer()#上报次数大于下一个周期再触发
+ self.heartreportTimer = osTimer()#心跳上报定时器
+
+ eventMesh.subscribe("get_network_state",self.get_network_state)#订阅消息
+ eventMesh.subscribe("set_network_state",self.set_network_state)#订阅消息
+
+ eventMesh.subscribe("set_dev_version",self.set_dev_version)#订阅消息
+ eventMesh.subscribe("get_dev_version",self.get_dev_version)#订阅消息
+
+ eventMesh.subscribe("set_dev_mac",self.set_dev_mac)#订阅消息
+ eventMesh.subscribe("get_dev_mac",self.get_dev_mac)#订阅消息
+
+ eventMesh.subscribe("set_dmp_cm_address",self.set_dmp_cm_address)#订阅消息
+ eventMesh.subscribe("get_dmp_cm_address",self.get_dmp_cm_address)#订阅消息
+
+ pass
+
+ def set_dmp_cm_address(self,event,msg):#设置网络是否正常
+ self.address = str(msg)
+ self.new_address = str(msg)
+
+ def get_dmp_cm_address(self,event,msg):#获取网络是否正常
+ return self.address
+
+ def set_network_state(self,event,msg):#设置网络是否正常
+ self.__net_connected = int(msg)
+
+ def get_network_state(self,event,msg):#获取网络是否正常
+ return self.__net_connected
+
+ def set_dev_version(self,event,msg):#获取固件版本号
+ self.software_version = str(msg)
+
+ def get_dev_version(self,event,msg):#获取固件版本号
+ return self.software_version
+
+ def set_dev_mac(self,event,msg):#设置BLE MAC地址
+ self.mac_data = str(msg)
+
+ def get_dev_mac(self,event,msg):#获取BLE MAC地址
+ return self.mac_data
+
+ def sha256_encode(self,key,data):#对数据进行AES256加密
+ h = hashlib.sha256()
+ h.update(key)
+ crypto_key = h.digest()
+ #IV是偏移量 默认16个十六进制00
+ IV = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+
+ crypto = aes(crypto_key, 2, IV)
+
+ #进行PKCS7Padding填充。
+ block_num = len(data) // BLOCK_SIZE+1
+ k = len(data) % BLOCK_SIZE
+ j = len(data) // BLOCK_SIZE
+ padding = BLOCK_SIZE - k
+ i = 0
+ szDataIn = bytearray(data)
+ # print(szDataIn)
+ szDataIn = szDataIn+bytearray(block_num * BLOCK_SIZE -len(data))
+ # print(szDataIn)
+
+ for i in range(padding):
+ szDataIn[j * BLOCK_SIZE + k + i] = padding
+ # print("szDataIn:{} {} {}\r\n".format(szDataIn,j * BLOCK_SIZE + k + i,padding))
+
+ indata = bytes(szDataIn)
+ enc = crypto.encrypt(indata)
+ #最后将加密AES256的数据转换成base64的编码格式
+ msg_tmp = base64.b64encode(enc)
+ data_encode = msg_tmp.decode('ascii')#转换成字符串
+ return data_encode
+
+ #写文件信息
+ def write_config_msg_file(self,msg):
+
+ print("write_config_msg_file msg:{}\r\n".format(msg))
+ with open("/usr/china_mobie_config.json",'w+',encoding="utf-8") as fd:
+ ujson.dump(msg,fd)
+ #读文件信息
+ def read_config_msg_file(self):
+ IFEXIST = ql_fs.path_exists("/usr/china_mobie_config.json") #不存在
+ if IFEXIST == True:
+ with open("/usr/china_mobie_config.json","r",encoding='utf-8') as fd:
+ self.config_data = ujson.load(fd)
+ print("read_config_msg_file self.config_data:{}\r\n".format(self.config_data))
+
+ def china_mobile_first_get_config(self,url):
+ ##############第一步#######获取采集规则配置#######
+ brand = "Watch"#品牌
+
+ model = "Watch"#型号
+ appKey = "M100001131"#不需要就填***appKey 厂商标识
+ sdkVersion = "***"#非SDK传输
+ apiVersion = "4.0.1"#接口定义 固定4.0.1
+ apiType = "I"#非Android
+ templateId = "TY000014"#根据产品分类在平台查询
+ IMEI = modem.getDevImei()
+ imei1 = IMEI#IMEI1或者CMEI
+ imei2 = "***"
+ configType = "autoRegist"#自注册填autoRegist 心跳配置传输 keepAlive
+ preField1 = "***"#预留字段1
+ preField2 = "***"#预留字段2
+ preField3 = "***"#预留字段3
+
+
+
+ #配置拉取数据格式
+ config_data = {"endpoint":"{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}".format(brand,model,appKey,sdkVersion,apiVersion,apiType,templateId,imei1,imei2,preField1,preField2,preField3),"configType":"{}".format(configType)}
+
+ #配置拉取数据上报地址
+ url = "https://{}//dm-multi-accept/multi/getMultiTerminalConfig".format(self.address)
+ headers_T ={"Content-Type":"application/json"}
+ print("ujson.dumps(config_data):{}".format(ujson.dumps(config_data)))
+ request_result = 0
+ result_json = ""
+ try:
+ response = request.post(url, data=ujson.dumps(config_data),headers =headers_T)
+ request_result = 1
+ if response.status_code == 200:#服务器响应成功并返回数据
+ content = response.content
+ c = next(content)
+ result_json = ujson.loads(c)
+ print("response.json:{}".format(ujson.loads(c)))
+ except Exception as e:
+ print("response:{}".format(e))
+ request_result = 0
+
+
+ if request_result == 0: #请求出错了
+ return ""
+
+
+ return result_json
+
+
+ def first_get_config_json(self):#开机上电获取配置信息
+ getresult = 0
+ print("first_get_config_json false",self.__net_connected)
+ if self.__net_connected != 1:#网络不正常
+ return getresult
+ url = "https://{}//dm-multi-accept/multi/getMultiTerminalConfig".format(self.address)
+ result_json = self.china_mobile_first_get_config(url)
+ if result_json == "":
+ return 0
+ # {
+ # "reportTime":1440,
+ # "reportNum":8,
+ # "heartBeatTime":1440,
+ # "retryInterval":10,
+ # "retryNum":1
+ # }#默认采集规则配置
+ #默认参数
+
+ retryInterval = self.retryInterval
+ heartBeatTime = self.heartBeatTime
+ reportTime = self.reportTime
+ reportNum = self.reportNum
+ retryNum = self.retryNum
+ new_address = self.address
+ print("get_config_json old:{} {} {} {} {} {}\r\n".format(reportTime,heartBeatTime,reportNum,retryInterval,retryNum,new_address))
+ if "rspCode" in result_json:#返回结课code 0000成功 其他参考文档
+ rspCode = result_json["rspCode"]
+ rspCode_zh = result_json["rspMsg"]
+ if rspCode == "0000" or rspCode_zh == "成功":
+ getresult = 1
+ if "result" in result_json:
+ msg_data = result_json["result"] #采集规则配置信息
+ if "ruleConfig" in msg_data:#不存在就是空
+ msg_data = msg_data["ruleConfig"]
+ msg_data = ujson.loads(msg_data)#转换成json格式
+ if "reportTime" in msg_data:
+ self.reportTime = int(msg_data["reportTime"])
+ if "heartBeatTime" in msg_data:
+ self.heartBeatTime = int(msg_data["heartBeatTime"])
+ if "reportNum" in msg_data:
+ self.reportNum = int(msg_data["reportNum"])
+ if "retryInterval" in msg_data:
+ self.retryInterval = int(msg_data["retryInterval"])
+ if "retryNum" in msg_data:
+ self.retryNum = int(msg_data["retryNum"])
+ if "address" in msg_data:
+ self.address = str(msg_data["address"])
+ print("get_config_json new:{} {} {} {} {}\r\n".format(self.reportTime,self.heartBeatTime,self.reportNum,self.retryInterval,self.retryNum,self.address))
+
+ print("true")
+ else:
+ print("false")
+
+ if getresult == 1:#请求配置文件成功
+ if (self.retryInterval != retryInterval) or (self.retryNum != retryNum) or (self.heartBeatTime != heartBeatTime) or\
+ (self.reportTime != reportTime) or (self.reportNum != reportNum) or (self.address != new_address):
+ #重新走注册流程 清空报错次数 记录当前时间戳
+ print("new config not old config!!!\r\n")#拉取的配置文件和保存本地的不一致
+ self.config_data["reportTime"] = self.reportTime
+ self.config_data["heartBeatTime"] = self.heartBeatTime
+ self.config_data["reportNum"] = self.reportNum
+ self.config_data["retryNum"] = self.retryNum
+ self.config_data["retryInterval"] = self.retryInterval
+ # self.config_data["address"] = str(self.address)
+ if new_address != self.address : #服务器下发和本地不一致需要用服务器下发的最新的IP 并把这个IP发送到BLE保存
+ eventMesh.publish("send_dmp_cm_address_toBLE",str(self.address))
+
+ self.write_config_msg_file(self.config_data) #保存新的配置文件
+ return 2
+ return getresult #1 获取成功 0 获取失败
+
+
+ def china_mobile_autoregist_infor(self,url,configType_data):
+ #########################第二步############自注册上报###################
+ #设备自注册上报
+ dev_autoregist_result = 0 #默认是1成功 0是失败
+ if self.__net_connected != 1:#网络不正常
+ return dev_autoregist_result
+ #密钥
+ key = "f74c005251dc40c4b64a283827da3812"
+
+ brand = "{}".format("Watch")#品牌
+
+ model = "Watch"#型号
+ appKey = "M100001131"#不需要就填***appKey 厂商标识
+ sdkVersion = "***"#非SDK传输
+ apiVersion = "4.0.1"#接口定义 固定4.0.1
+ apiType = "I"#非Android
+ templateId = "TY000014"#根据产品分类在平台查询
+ IMEI = modem.getDevImei()
+ imei1 = IMEI#IMEI1或者CMEI
+ imei2 = "***"
+ configType = configType_data#自注册填autoRegist 心跳配置传输 keepAlive 暂时不用
+ preField1 = "***"#预留字段1
+ preField2 = "***"#预留字段2
+ preField3 = "***"#预留字段3
+
+ #不需要加密 #||分隔符不能超过11个 否则平台会解析出错
+ config_data = "{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}||{}".format(brand,model,appKey,sdkVersion,apiVersion,apiType,templateId,imei1,imei2,configType,preField1,preField2)
+
+ #需要加密的数据明文
+ if (len(self.mac_data) == 0):#获取失败了
+ self.mac_data = "***"
+
+ MAC = self.mac_data
+ # base64_MAC = sha256_encode(key,MAC)
+ RAM = "32MB"
+ # base64_RAM = sha256_encode(key,RAM)
+ ROM = "144MB"
+ # base64_ROM = sha256_encode(key,ROM)
+ CPU = "YH601S"
+ # base64_CPU = sha256_encode(key,CPU)
+ sysVersion = "OpenHarmony 3.2"
+ # base64_sysVersion = sha256_encode(key,sysVersion)
+ if (len(self.software_version) == 0):#获取失败了
+ self.software_version = "Watch Soar V1.0"
+ softwareVer = self.software_version
+ # base64_softwareVer = sha256_encode(key,softwareVer)
+ softwareName ="FD230"
+ # base64_softwareName = sha256_encode(key,softwareName)
+ volte="0" #0:开;1:关;-1:不支持
+ # base64_volte = sha256_encode(key,volte)
+ netType="4G"
+ # base64_netType = sha256_encode(key,netType)
+
+ resolution="466*466"
+ # base64_resolution = sha256_encode(key,resolution)
+
+ screenSize = "1.43"
+ # base64_screenSize = sha256_encode(key,screenSize)
+ wearingStatus ="-1"
+ # base64_wearingStatus = sha256_encode(key,wearingStatus)
+
+ networkStatus ="1"#1:连接;0:未连接;-1:不支持
+
+ routerMac = "***"
+
+ wifiMac = "***"
+ # base64_networkStatus = sha256_encode(key,networkStatus)
+ encyr_data = [MAC,RAM,ROM,CPU,sysVersion,softwareVer,softwareName,volte,netType,resolution,screenSize,wearingStatus,networkStatus,routerMac,wifiMac]
+ print(len(encyr_data))
+ encyr_new_data=[]
+ for i in range(len(encyr_data)):
+ tmp_data = self.sha256_encode(key,encyr_data[i])
+ encyr_new_data.append(tmp_data)
+
+ # deviceInfo_tmp = {
+ # "bluetoothMac":"{}".format(base64_MAC),#mac地址可填可不填
+ # "ram":"{}".format(base64_RAM),#ram信息
+ # "rom":"{}".format(base64_ROM),#rom信息
+ # "cpu":"{}".format(base64_CPU),#cpu信息
+ # "sysVersion":"{}".format(base64_sysVersion),#操作系统版本号
+ # "softwareVer":"{}".format(base64_softwareVer),#固件版本号
+ # "softwareName":"{}".format(base64_softwareName),#固件名称
+ # "volte":"{}".format(base64_volte),#volte开关 默认是开
+ # "netType":"{}".format(base64_netType),#当前网络类型4G
+ # "resolution":"{}".format(base64_resolution),#屏幕分辨率466*466
+ # "screenSize":"{}".format(base64_screenSize),#屏幕尺寸默认1.43
+ # "wearingStatus":"{}".format(base64_wearingStatus),#佩戴状态不支持
+ # "networkStatus":"{}".format(base64_networkStatus)#网络状态
+
+ # }
+ deviceInfo_tmp = {
+ "bluetoothMac":"{}".format(encyr_new_data[0]),#mac地址可填可不填
+ "ram":"{}".format(encyr_new_data[1]),#ram信息
+ "rom":"{}".format(encyr_new_data[2]),#rom信息
+ "cpu":"{}".format(encyr_new_data[3]),#cpu信息
+ "sysVersion":"{}".format(encyr_new_data[4]),#操作系统版本号
+ "softwareVer":"{}".format(encyr_new_data[5]),#固件版本号
+ "softwareName":"{}".format(encyr_new_data[6]),#固件名称
+ "volte":"{}".format(encyr_new_data[7]),#volte开关 默认是开
+ "netType":"{}".format(encyr_new_data[8]),#当前网络类型4G
+ "resolution":"{}".format(encyr_new_data[9]),#屏幕分辨率466*466
+ "screenSize":"{}".format(encyr_new_data[10]),#屏幕尺寸默认1.43
+ "wearingStatus":"{}".format(encyr_new_data[11]),#佩戴状态不支持
+ "networkStatus":"{}".format(encyr_new_data[12]),#网络状态
+ "routerMac":"{}".format(encyr_new_data[13]), #路由mac地址 ***
+ "mac":"{}".format(encyr_new_data[14]) #wifi mac
+ }
+ json_data = ujson.dumps(deviceInfo_tmp)#需要转义的字符串
+
+ send_autoregist = {
+ "endpoint":config_data,
+ "deviceInfo":"{}".format(json_data)
+ }
+
+ test_data = ujson.dumps(send_autoregist)#需要转义的字符串
+ print("test_data:{}".format(test_data))
+ headers_T ={"Content-Type":"application/json"}
+ request_result = 0
+ print("shangbao address:{}\r\n".format(url))
+ try:
+ response = request.post(url, data=ujson.dumps(send_autoregist),headers =headers_T)
+ request_result = 1
+ result_json = ""
+ print("response success:response.status_code{}\r\n".format(response.status_code))
+ if response.status_code == 200:
+ dev_autoregist_result = 1
+ content = response.content
+ c = next(content)
+ result_json = ujson.loads(c)#解析成json格式
+ else:
+ dev_autoregist_result = 0
+
+
+ if "rspCode" in result_json:
+ rspCode = result_json["rspCode"]
+ rspMsg = result_json["rspMsg"]
+ print("response success:rspCode{} {}\r\n".format(rspMsg,rspCode))
+ if rspCode == "0000" or rspMsg == "成功":
+ dev_autoregist_result = 1
+ else:
+ dev_autoregist_result = 0
+ else:
+ dev_autoregist_result = 0
+ print("response success:\r\n")
+ return dev_autoregist_result
+
+ except Exception as e:
+ print("response:{}".format(e))
+ request_result = 0
+
+ if request_result == 0:#请求出错了
+ dev_autoregist_result = 0
+ return dev_autoregist_result
+
+
+ def read_config_file(self):#获取配置文件,一开机是没有配置文件的
+
+ self.read_config_msg_file()#读文件信息
+ if self.config_data != {}:
+ if "retryInterval" in self.config_data:
+ self.retryInterval = int(self.config_data["retryInterval"])
+ if "retryNum" in self.config_data:
+ self.retryNum = int(self.config_data["retryNum"])
+ if "heartBeatTime" in self.config_data:
+ self.heartBeatTime = int(self.config_data["heartBeatTime"])
+ if "reportTime" in self.config_data:
+ self.reportTime = int(self.config_data["reportTime"])
+ if "reportNum" in self.config_data:
+ self.reportNum = int(self.config_data["reportNum"])
+ if "address" in self.config_data:
+ self.address = str(self.config_data["address"])
+
+ #终端本地需要保存本地的数据
+ # self.reportTime_Sec = 0 #保存本地 保存时间戳下一次开机使用
+ # self.report_Num_old = 0#保存本地
+ # self.retryNum_old = 3#保存本地
+ if NEED_SAVE_CONFIG_FILE == 1:
+ if "reportTime_Sec" in self.config_data:
+ self.reportTime_Sec = int(self.config_data["reportTime_Sec"])
+ if "report_Num_old" in self.config_data:
+ self.report_Num_old = int(self.config_data["report_Num_old"])
+ if "retryNum_old" in self.config_data:
+ self.retryNum_old = int(self.config_data["retryNum_old"])
+
+ print("read_config_file self.config_data:{} ".format(self.config_data))
+ def retryTimerCb(self,*argc):#异常重试机制定时器回调
+ #保存本地
+ self.retryNum_old+=1 #1 self.reportNum = 1
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["retryNum_old"] = self.retryNum_old
+ self.write_config_msg_file(self.config_data)
+ print("retryTimerCb self.retryNum_old:{}\r\n".format(self.retryNum_old))
+ self.search_report_num_step()
+ pass
+ def reportTimerIntervalError(self):
+ self.retryNum_old = 0#保存
+ self.report_Num_old = 0#保存 定时清空数据
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)#获取时间戳
+ self.reportTime_Sec = time_tmp+self.reportTime*60 #(记录时间+reportTime)标识旧的时间
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["reportTime_Sec"] = self.reportTime_Sec
+ self.config_data["retryNum_old"] = self.retryNum_old
+ self.config_data["report_Num_old"] = self.report_Num_old
+ self.write_config_msg_file(self.config_data)
+ self.search_report_num_step()#重新查询
+ pass
+ def error_retryNum_step(self):#判读报错次数是否大于self.retryNum 步骤
+ print("error_retryNum_step:self.retryNum_oldd:{} self.retryNum:{} self.reportTime:{}\r\n".format(self.retryNum_old,self.retryNum,self.reportTime))
+
+ if self.retryNum_old >= self.retryNum and self.retryNum_old != 0:#self.retryNum_old > 10#结束HTPP下一个最大频率周期时间间隔流程
+ print("error_retryNum_step:self.retryNum_old >= self.retryNum\r\n")
+ self.reportTimerIntervalError()
+ # self.retpoertTimerC.start(self.reportTime*60*1000,0,self.reportTimerIntervalError)#重新开始 需要清空数据
+ else:
+ get_result = self.first_get_config_json()#发起向服务端请求配置信息下发到设备端
+ if get_result == 0:#获取失败或者没有网络 走异常重试机制
+ self.report_Num_old+=1#请求错误请求失败都要保存上报次数
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["report_Num_old"] = self.report_Num_old
+ self.write_config_msg_file(self.config_data)
+ print("error_retryNum_step:self.retryTimer.start :{} {} {}\r\n".format(self.retryInterval,self.report_Num_old,self.reportNum))
+ self.checkMaxReportNum()#检查上报最大次数
+ self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb)
+ pass
+ else:#
+
+ #第一步触发自注册
+ if get_result == 2:#请求的配置文件和本地不一致重启
+ self.retryNum_old = 0#保存本地 配置文件不同重启模组 清空异常重试的报错次数
+ # self.report_Num_old+=1#请求错误请求失败都要保存上报次数
+ # if NEED_SAVE_CONFIG_FILE == 1:
+ # self.config_data["report_Num_old"] = self.report_Num_old
+ # self.config_data["retryNum_old"] = self.retryNum_old
+ # self.write_config_msg_file(self.config_data)
+
+ self.china_mobile_init_param()#重新走流程读配置文件->判断上报总数->判断报错次数->获取配置文件
+ self.search_report_num_step()
+ return
+
+ self.report_Num_old+=1#请求错误请求失败都要保存上报次数
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["report_Num_old"] = self.report_Num_old
+ self.write_config_msg_file(self.config_data)
+ print("error_retryNum_step self.report_Num_old:{}\r\n".format(self.report_Num_old))
+ if self.checkMaxReportNum() == 1:#检查上报最大次数
+ self.search_report_num_step()#重新查询
+ return
+ report_result = self.onself_regist_report_cb()#注册
+
+ #第二步触发心跳上报次数
+ if report_result == 1:#注册完成之后根据服务端下发的配置 间隔上报心跳
+ self.heartreportTimer.stop()
+ self.heartreportTimer.start(self.heartBeatTime*60*1000,1,self.heartreportTimerCb)
+
+ def heartreportTimerCb(self,*argc):
+ self.heart_report_cb()
+
+ def retpoertTimerClear(self):
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)#获取时间戳
+ print("retpoertTimerCB time_tmp -self.reportTime_Sec:{} time_tmp :{} self.reportTime_Sec:{}\r\n".format(self.reportTime_Sec-time_tmp,time_tmp,self.reportTime_Sec))
+ self.report_Num_old = 0#清空上报总次数 #保存本地
+ self.retryNum_old = 0#清空上报错误次数 #保存本地
+ self.reportTime_Sec = time_tmp+self.reportTime*60#记录当前时间+reportTime的时间用于下次错判断
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["reportTime_Sec"] = self.reportTime_Sec
+ self.config_data["retryNum_old"] = self.retryNum_old
+ self.config_data["report_Num_old"] = self.report_Num_old
+ self.write_config_msg_file(self.config_data)
+ self.retpoertTimerC.stop()#关闭定时器
+ self.error_retryNum_step()#清空报错次数重新走判断报错次数
+ pass
+ def check_current_time(self):#检测当前时间是否超过self.reportTime 超过清空报错次数 清空上报总次数
+ #
+ date_tmp = utime.localtime()
+ currentTime = utime.mktime(date_tmp)#获取时间戳
+ reportTime = self.reportTime_Sec
+ print("check_current_time:time_tmp - self.reportTime_Sec:{} currentTime:{} self.reportTime*60:{}".format(reportTime, currentTime,self.reportTime*60))
+ if currentTime >= reportTime:#当前时间是否大于上次记录的时间 currentTime >= reportTime 直接清空 不超过定时清空数据不再上报数据
+ #在规定时间内上报次数大于8次就要等下一个10分钟 或者1440分了开个定时器
+ print("currentTime >= reportTime:\r\n")
+ self.retpoertTimerClear()
+ else:#否则次数置零,记录一下(当前时间+reportTime)时间
+ time_count = (reportTime - currentTime) #self.reportTime_Sec永远比time_tmp大
+ print("time_count:{}".format(time_count))
+ print("currentTime < reportTime:\r\n")
+ self.retpoertTimerC.start(time_count*1000,0,self.retpoertTimerCB)
+
+
+ # 第一次请求的时候,记录一下(当前时间+reportTime)时间与次数,如果次数小于最大次数,直接返回true。
+ # 如果次数大于最大次数,则判断一下当前时间是否超过上次设置的时间,如果超过了,则表示超过最大次数;否则次数置零,记录一下(当前时间+reportTime)时间。
+ def retpoertTimerCB(self,*argc):#按照剩余的时间做定时器
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)#获取时间戳
+ print("retpoertTimerCB time_tmp -self.reportTime_Sec:{} time_tmp :{} self.reportTime_Sec:{}\r\n".format(self.reportTime_Sec-time_tmp,time_tmp,self.reportTime_Sec))
+ self.report_Num_old = 0#清空上报总次数 #保存本地
+ self.retryNum_old = 0#清空上报错误次数 #保存本地
+ self.reportTime_Sec = time_tmp+self.reportTime*60#记录当前时间+reportTime的时间用于下次错判断
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["reportTime_Sec"] = self.reportTime_Sec
+ self.config_data["retryNum_old"] = self.retryNum_old
+ self.config_data["report_Num_old"] = self.report_Num_old
+ self.write_config_msg_file(self.config_data)
+ self.error_retryNum_step()#清空报错次数重新走判断报错次数
+
+
+ def search_report_num_step(self):#查询上报总数步骤
+ print("search_report_num_step:self.retryInterval:{} self.retryNum:{}".format(self.report_Num_old,self.reportNum))
+ if self.report_Num_old >= self.reportNum and self.report_Num_old != 0:#查询上报的总次数是否大于存储上报总次数
+ self.check_current_time()#检测当前时间是否超过self.reportTime 超过清空报错次数 清空上报总次数
+ else:#
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)#获取时间戳
+ self.reportTime_Sec = time_tmp+self.reportTime*60 #(记录时间+reportTime)标识旧的时间
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["reportTime_Sec"] = self.reportTime_Sec
+ self.write_config_msg_file(self.config_data)
+ self.error_retryNum_step()#查询上报错误次数
+
+ def search_report_num_step_init(self):#查询上报总数步骤
+ print("search_report_num_step:self.retryInterval:{} self.retryNum:{} self.reportTime_Sec:{}\r\n".format(self.report_Num_old,self.reportNum,self.reportTime_Sec))
+ if self.report_Num_old >= self.reportNum and self.report_Num_old != 0:#查询上报的总次数是否大于存储上报总次数
+ self.check_current_time()#检测当前时间是否超过self.reportTime 超过清空报错次数 清空上报总次数
+ else:#
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)#获取时间戳
+ if self.reportTime_Sec == 0:
+ self.reportTime_Sec = time_tmp+self.reportTime*60 #(记录时间+reportTime)标识旧的时间
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["reportTime_Sec"] = self.reportTime_Sec
+ self.write_config_msg_file(self.config_data)
+ self.error_retryNum_step()#查询上报错误次数
+
+
+ def reportTimerIntervalCb(self,*argc):#最大上报频率时间间隔定时器 要清空数据
+ print("reportTimerIntervalCb\r\n")
+ self.search_report_num_step()#重新查询
+
+ def onself_regist_report_cb(self):#自注册上报信息
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)#获取时间戳
+ print("onself_regist_report_cb:self.report_Num_old:{} self.reportNum:{} self.reportTime_Sec:{}\r\n".format(self.report_Num_old,self.reportNum,self.reportTime_Sec))
+ self.report_Num_old+=1 ##保存本地
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["report_Num_old"] = self.report_Num_old
+ self.write_config_msg_file(self.config_data)
+ #设备自注册上报信息
+ url = "https://{}//dm-multi-accept/multi/acceptMultiTerminalRegInfo".format(self.address)#上报地址
+ confing_type = "autoRegist"#上报传输配置
+ result = self.china_mobile_autoregist_infor(url,confing_type)
+
+
+ if result != 1:
+ #触发异常重试进制
+ self.checkMaxReportNum()#检查上报最大次数
+ if self.checkMaxRetryNum() == 1:
+ print("retryTimerCb timer22")#异常重试过多重新间隔reportTime注册流程 关闭所有的定时器
+ self.search_report_num_step()#重新查询
+ return 0
+ self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb)
+ return 0
+ else:
+ if self.checkMaxReportNum() == 1:
+ self.search_report_num_step()#重新查询
+ # self.retpoertTimerC.start(self.reportTime*60*1000,0,self.reportTimerIntervalCb)
+ return 0
+ else:
+ return 1
+ def checkMaxReportNum(self):#检查上报次数最大值
+ print("checkMaxReportNum :self.reportNum :{} self.report_Num_old:{}\r\n".format(self.reportNum,self.report_Num_old))
+ if self.report_Num_old >= self.reportNum and self.report_Num_old != 0:
+ self.retryTimer.stop()#关定时器
+ self.retpoertTimerC.stop()
+ self.heartreportTimer.stop()
+ return 1
+ else:
+ return 0
+
+ def checkMaxRetryNum(self):#检查上报错误次数
+ print("checkMaxRetryNum :self.retryNum:{} self.retryNum_old:{}\r\n".format(self.retryNum_old,self.retryNum))
+ if self.retryNum_old >= self.retryNum and self.retryNum_old != 0:#异常重试过多重新间隔reportTime注册流程
+ self.retryTimer.stop()#关定时器
+ self.retpoertTimerC.stop()
+ self.heartreportTimer.stop()#关闭心跳定时器
+ return 1
+ else:
+ return 0
+
+ def heart_report_cb(self):#心跳上报信息
+
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)#获取时间戳
+ self.report_Num_old+=1#保存本地
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["report_Num_old"] = self.report_Num_old
+ self.write_config_msg_file(self.config_data)
+ print("heart_report_cb:self.report_Num_old:{} self.reportNum:{} self.reportTime:{} self.reportTime_Sec:{}\r\n".format(self.report_Num_old,self.reportNum,self.reportTime,self.reportTime_Sec))
+
+ url = "https://{}//dm-multi-accept/multi/acceptMultiTerminalHeartbeatInfo".format(self.address)#上报地址
+ confing_type = "keepAlive"#上报传输配置
+ result = self.china_mobile_autoregist_infor(url,confing_type)
+ if result != 1:
+ #触发异常重试进制
+ self.checkMaxReportNum()
+ if self.checkMaxRetryNum() == 1:#异常重试过多重新间隔reportTime注册流程
+ self.search_report_num_step()#重新查询
+ return
+ self.retryTimer.start(self.retryInterval*60*1000,0,self.retryTimerCb)
+ return
+ if self.checkMaxReportNum() == 1:#上报次数大于8次
+ self.search_report_num_step()#重新查询
+ return
+
+ def china_mobile_init_param(self):#初始化
+
+ status = eventMesh.publish("get_factory_status")
+ if status == None:
+ status = 0
+ print("get_factory_status:{}\r\n".format(status))
+ if status == 0:#恢复出厂或者新的机器需要清空不必要的数据
+ if self.init_flag == 0:#只初始化一次
+ IFEXIST = ql_fs.path_exists("/usr/telecom_config.json") #不存在
+ if IFEXIST == True:
+ uos.remove("/usr/telecom_config.json")
+ isStorage = ql_fs.path_exists("/usr/china_mobie_config.json")#移动入库的配置文件移除
+ if isStorage == True:
+ uos.remove("/usr/china_mobie_config.json")
+ #先清空再写入默认参数
+ self.init_flag = 1
+ self.retryInterval = 10
+ self.retryNum = 1#异常重试最大次数
+ self.heartBeatTime = 1440#心跳上报频率 单位分钟
+ self.reportTime = 1440#最大上报频率 自注册+心跳上报的频率次数不能大于最大上报频率次数
+ self.reportNum = 8 #最大上报次数
+
+ self.reportTime_Sec = 0 #保存本地 保存时间戳下一次开机使用
+ self.report_Num_old = 0#保存本地
+ self.retryNum_old = 0#保存本地
+ get_address = eventMesh.publish("get_dmp_cm_address")
+ if get_address == None:#获取出来地址是空的使用适配地址
+ self.address = "a.fxltsbl.com"#默认
+ else: #恢复出厂使用BLE传送过来的地址
+ self.address = str(eventMesh.publish("get_dmp_cm_address"))
+
+ self.config_data["retryInterval"] = self.retryInterval
+ self.config_data["retryNum"] = self.retryNum
+ self.config_data["heartBeatTime"] = self.heartBeatTime
+ self.config_data["reportTime"] = self.reportTime
+ self.config_data["reportNum"] = self.reportNum
+ # self.config_data["address"] = self.address
+ if NEED_SAVE_CONFIG_FILE == 1:
+ self.config_data["reportTime_Sec"] = self.reportTime_Sec
+ self.config_data["report_Num_old"] = self.report_Num_old
+ self.config_data["retryNum_old"] = self.retryNum_old
+
+ self.write_config_msg_file(self.config_data)
+ #读配置文件
+ self.read_config_file()#只读一下配置文件
+
+ self.retryTimer.stop()#关定时器
+ self.retpoertTimerC.stop()
+ self.heartreportTimer.stop()
+ def china_mobile_init(self):
+ self.china_mobile_init_param()
+ #查询上报总数流程
+ self.search_report_num_step_init()
+
+
+
+
+chinamobileCb = chinamobile()
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+#远程升级
+
+import fota
+import utime
+import log
+import checkNet
+
+import app_fota
+from misc import Power
+import modem
+import ujson
+import request
+import ql_fs
+import checkNet
+import sys
+
+#远程升级
+import uos
+
+
+# 设置日志输出级别
+
+class httpota:
+ def __init__(self):
+ print("httpota init")
+
+
+ def run(url_1,url_2):
+ print("httpDownload...{}".format(url_1))
+ print("httpDownload...{}".format(url_2))
+ # format(str(url_2)))
+ fota_obj = fota() # 创建Fota对象
+ # res = fota_obj.httpDownload(str(url_1),str(url_2))
+ res = fota_obj.httpDownload(url1="{}".format(url_1),url2="{}".format(url_2))
+ if res != 0:
+ print.error("httpDownload error")
+ return
+ print("wait httpDownload update...")
+ utime.sleep(2)
+ # Power.powerRestart()
+
+# httpota = httpota()
+# httpota.run("http://snicker.com.cn:8089/FD230/V18-V19OTA")
\ No newline at end of file
--- /dev/null
+import example
+main_flag = 1
+try:
+ from usr.slipService import slipservice
+ from usr.tcpService import TcpService
+ import usr.checkota
+ example.exec('/usr/main_init.py')
+ print("启动成功!!!!!\r\n")
+except Exception as e:
+ main_flag = 0
+ print("启动失败!!!!!\r\n".format(e))
+
+
+
+
--- /dev/null
+import example
+import osTimer
+import ql_fs
+import log
+import sms
+from misc import Power
+ota_flag = 0
+try:
+ from usr.EventMesh import eventMesh
+ from usr.telecom_dmp import telecomDmpCb
+ from usr.china_mobile_dmp import chinamobileCb
+ from usr.cat1Service import cat1service
+ ota_flag = 1
+ print("检测文件成功!!!!!!!\r\n")
+except Exception as e:
+ print("检测文件失败!!!!!!!{}\r\n".format(e))
+ ota_flag = 0
+tmp_dir = ql_fs.path_exists("/usr/TmpPyFile") #临时存放的文件夹
+if tmp_dir == True:
+ try:
+ ql_fs.rmdirs("/usr/TmpPyFile")
+ print("移除 TmpPyFile 成功!!!!!!!\r\n")
+ except Exception as e:
+ print("移除 TmpPyFile 失败!!!!!!!{}\r\n".format(e))
+
+sms_get = sms.getSaveLoc()
+if(sms_get != -1):
+ sms_lacv = sms_get[0][0]
+ if sms_lacv != 'SM': #每次开机设置一下短信的存储位置
+ sms.setSaveLoc('SM', 'SM', 'SM')
+
+PROJECT_VERSION = "PY_MAIN_V3"
+CONFIG_JSON="/usr/system_config.json"
+CURRENT_APP_TYPE="pymain"
+
+
+# 设置日志输出级别
+log.basicConfig(level=log.INFO)
+cat1service_log = log.getLogger("pymain")
+
+
+def get_versionkeyname_by_py(app_type):
+ return str("{}version".format(app_type))
+
+def get_default_versionvalue_by_py(app_type):
+ if (app_type == "pymain"):
+ return "PY_MAIN_V2"
+ elif (app_type == "pyota"):
+ return "PY_OTA_V2"
+ elif (app_type == "pysrv"):
+ return "PY_SRV_V2"
+
+#如果没有configfile则创建它
+if not ql_fs.path_exists(CONFIG_JSON):
+ data = {str(get_versionkeyname_by_py(CURRENT_APP_TYPE)):get_default_versionvalue_by_py(CURRENT_APP_TYPE)}
+ ql_fs.touch(CONFIG_JSON,data)
+
+def set_version_to_json_config(app_type,keyvalue):
+ config_data = ql_fs.read_json(CONFIG_JSON)
+ config_data.update( {str(get_versionkeyname_by_py(app_type)):keyvalue})
+ ql_fs.touch(CONFIG_JSON, config_data)
+ cat1service_log.info("{}={}".format(get_versionkeyname_by_py(app_type),keyvalue))
+ cat1service_log.info("{}".format(config_data))
+
+set_version_to_json_config(CURRENT_APP_TYPE,PROJECT_VERSION)
+
+
+def checkota_cb(arg):
+ print("start checkota!!")
+ example.exec('/usr/checkota.py')
+# 创建os定时器
+
+timer = osTimer()
+# 启动定时器,参数依次为时间、是否循环、回调函数 定时器超时的时间(单位ms)
+# 开机delay 20秒后执行一次ota升级
+timer.start(20000,0,checkota_cb)
+print("checkota py end!!")
--- /dev/null
+
+import log
+import slip
+from machine import UART
+class slipServiceInit:
+ AP = 0 # SLIP_INNER
+ STA = 1 # SLIP_OUTER
+ def __init__(self, uart=UART.UART4, mode=AP):
+ self.__uart = uart
+ self.__mode = mode
+ slip.destroy()
+ print('slip uart={0}'.format (self.__uart))
+
+ ret = slip.construct(self.__uart, self.__mode, 0)
+ if ret != 0:
+ print('slip netif construct fail')
+ else:
+ print('slip netif construct success')
+
+slipservice = slipServiceInit()
\ No newline at end of file
--- /dev/null
+import app_fota
+from misc import Power
+import modem
+import ujson
+import request
+import ql_fs
+import checkNet
+import sys
+import sim
+
+from queue import Queue
+import usys
+import _thread
+import fota
+import utime
+import log
+import uos
+import osTimer
+import net
+import ql_fs
+from usr.EventMesh import eventMesh,CHINA_TELECOM_DM_FUN_ENABLE
+# 设置日志输出级别
+log.basicConfig(level=log.INFO)
+fota_log = log.getLogger("telecom_dmp")
+import modem
+import base64
+import request
+import ujson
+REGIST_MAX_NUM=10 #自注册的最大次数 现在是默认是10次
+REGIST_INTERVAL_TIMER=60*60 #自注册失败的间隔时间 1小时
+REGIST_POWER_ON_TIME=5*60 #开机5分钟内就必须自注册触发
+MULTI_DAY_RESEND_T = 30*24*60*60-12*60*60#多日重发的机制的周期T 30天
+MULTI_DAY_RESEND_t = 12*60*60#多日重发的机制的周期t 0.5天
+def get_report_url_website(mode = None):#获取上报网址
+ url = "http://zzhc.vnet.cn:9998/"#上报网址
+ return url
+
+class telecomDmp:
+ def __init__(self):
+ self.config_data = {}
+ self.check_timer = osTimer()#1小时定时器
+ self.multiDayResend_timer = osTimer()#12小时定时器 多日重发的机制
+ self.telecomTimer = osTimer()
+ self.multimer_count = 0#多日重发机制周期Count
+ self.multimer_init = 0
+ self.power_on_multiflag = 0
+ self.timer_count = 0
+ self.timerPowerNum = 0
+ self.telecom_init_state = 0#初始化状态开机检查标识
+ self.isRegistOk = 0#注册成功
+ eventMesh.subscribe("get_telecom_init_state",self.get_telecom_init_state)
+ eventMesh.subscribe("set_telecom_init_state",self.set_telecom_init_state)
+
+ eventMesh.subscribe("set_dmp_power_num",self.set_dmp_power_num)
+ eventMesh.subscribe("get_dmp_power_num",self.get_dmp_power_num)
+
+ eventMesh.subscribe("get_dmp_power_timer_count",self.get_dmp_power_timer_count)
+
+ self.regist_queue = Queue()
+ _thread.stack_size(10*1024)
+ _thread.start_new_thread(self.regist_queue_thread, ())
+ _thread.stack_size(8*1024)
+
+ eventMesh.subscribe("publish_message_event_registinfor",self.publish_message_event_registinfor)
+ self.__net_connected = 0
+ eventMesh.subscribe("get_network_state",self.get_network_state)#订阅消息
+ eventMesh.subscribe("set_network_state",self.set_network_state)#订阅消息
+
+ eventMesh.subscribe("set_dev_version",self.set_dev_version)#订阅消息
+ eventMesh.subscribe("get_dev_version",self.get_dev_version)#订阅消息
+
+ eventMesh.subscribe("save_iccid_data",self.save_iccid_data)#订阅消息 保存ICCID
+ eventMesh.subscribe("get_iccid_data",self.get_iccid_data)#订阅消息 保存ICCID
+
+ eventMesh.subscribe("set_regist_time",self.set_regist_time)#订阅消息 保存ICCID
+ eventMesh.subscribe("get_regist_time",self.get_regist_time)#订阅消息 保存ICCID
+
+ self.regist_timeSec = 0
+ self.iccid_data = ""
+ self.software_version = ""
+ self.mulit_day_timesec = 0#多日重发的开始的时间戳
+ pass
+ def regist_queue_thread(self):
+ while True:
+ data = self.regist_queue.get()
+ #EventMesh.debug_log("regist_queue:data = {}".format(data))
+ if data != None:
+ try:
+ data["func"](data["data"])
+ except Exception as e:
+ print("regist_queue:ERROR:{}".format(e))
+ usys.print_exception(e)
+ def publish_message_event_registinfor(self,event,msg):
+ self.regist_queue.put(msg)
+
+ def publish_regist_event_cb(self, *args, **kwargs):
+ eventMesh.publish("publish_message_event_registinfor",{"func":self.timer_cb,"data":0})
+
+ def set_network_state(self,event,msg):#设置网络是否正常
+ self.__net_connected = int(msg)
+
+ def get_network_state(self,event,msg):#获取网络是否正常
+ return self.__net_connected
+
+ def set_dev_version(self,event,msg):#获取固件版本号
+ self.software_version = str(msg)
+
+ def get_dev_version(self,event,msg):#获取固件版本号
+ return self.software_version
+
+ def save_iccid_data(self,event,msg):
+ self.iccid_data = str(msg)[6:]#ICCID:
+ print("write_config_msg_file msg:{}\r\n".format(msg))
+ self.config_data["ICCID"]=self.iccid_data
+ with open("/usr/telecom_config.json",'w+',encoding="utf-8") as fd:
+ ujson.dump(self.config_data,fd)
+ #读文件信息
+ def get_iccid_data(self,event,msg):
+
+ IFEXIST = ql_fs.path_exists("/usr/telecom_config.json") #不存在
+ if IFEXIST == True:
+ with open("/usr/telecom_config.json","r",encoding='utf-8') as fd:
+ self.config_data = ujson.load(fd)
+ print("get_iccid_data self.config_data:{}\r\n".format(self.config_data))
+ if self.config_data != {}:
+ if "ICCID" in self.config_data:
+ value = self.config_data["ICCID"]
+ self.iccid_data = str(value)
+ else:
+ self.iccid_data = ""
+ print("get_iccid_data self.config_data end:{}\r\n".format(self.config_data))
+ return self.iccid_data
+
+ def set_regist_time(self,event,msg):#
+ self.regist_timeSec = str(msg)[7:]#REGIST:
+ print("set_regist_time msg:{}\r\n".format(msg))
+ self.config_data["REGIST"]=self.regist_timeSec
+ with open("/usr/telecom_config.json",'w+',encoding="utf-8") as fd:
+ ujson.dump(self.config_data,fd)
+
+ def get_regist_time(self,event,msg):#
+ IFEXIST = ql_fs.path_exists("/usr/telecom_config.json") #不存在
+ if IFEXIST == True:
+ with open("/usr/telecom_config.json","r",encoding='utf-8') as fd:
+ self.config_data = ujson.load(fd)
+ print("get_regist_time self.config_data:{}\r\n".format(self.config_data))
+ if self.config_data != {}:
+ if "REGIST" in self.config_data:
+ value = self.config_data["REGIST"]
+ self.regist_timeSec = int(value)
+ else:
+ self.regist_timeSec = 0
+ return self.regist_timeSec
+
+
+ def get_sim_state(self):#获取sim状态 不为1是sim异常
+ return sim.getStatus()
+
+ def get_sim_iccid(self):#获取sim的iccid
+ return sim.getIccid()
+
+ def get_sim_imsi(self):#获取sim的imsi
+ return sim.getImsi()
+ def get_dev_imei(self):#获取设备的imei号
+ return modem.getDevImei()
+
+ def telecom_regeist_infor(self):#自注册信息 可变更
+ network_state = eventMesh.publish("get_network_state")
+ print("telecom_regeist_infor :",network_state,self.isRegistOk,REGIST_INTERVAL_TIMER,MULTI_DAY_RESEND_T,MULTI_DAY_RESEND_t,REGIST_POWER_ON_TIME)
+ if network_state == 0:# 第一次进入网络不正常就需要开启1小时定时器 等待下一个周期判断网络是否正常 需要判断网络是否正常 不正常就不去触发自注册了 就等待下一次 如果10次都不成功 就等一下次开机再去自注册
+ self.timer_count+=1
+ print("self.timer_count:{}".format(self.timer_count))
+ if self.timer_count < REGIST_MAX_NUM:#总共是10次 10次结束还没有自注册成功就等下一次开机自注册
+ self.check_timer.start(REGIST_INTERVAL_TIMER*1000,0,self.publish_regist_event_cb)#不需要循环定时器
+ else:
+ self.multiple_day_resend()
+ return
+ iccid = self.get_sim_iccid()
+ read_iccid = eventMesh.publish("get_iccid_data")
+ if read_iccid == None:
+ read_iccid = ""
+
+ print("iccid!!!!!!!!!!iccid {} read_iccid:{}".format(iccid,read_iccid))
+ if read_iccid != "":
+ if str(read_iccid) == str(iccid):#两者相同 并且本地有保存 不再自注册了 说明已经自注册过了
+ print("already registed!!!!!!") #已自注册过
+ self.isRegistOk = 1
+
+ if self.isRegistOk == 1:
+ print("multiple_day_resend!!!!!!\r\n")
+ self.multiple_day_resend()
+ return
+ self.telecom_regist_infor_init()#自注册初始化函数
+ if self.isRegistOk == 0:
+ self.timer_count+=1
+ print("self.timer_count:{}".format(self.timer_count))
+ if self.timer_count < REGIST_MAX_NUM:#总共是10次 10次结束还没有自注册成功就等下一次开机自注册
+ self.check_timer.start(REGIST_INTERVAL_TIMER*1000,0,self.publish_regist_event_cb)#不需要循环定时器
+ else:
+ self.multiple_day_resend()
+
+ def telecom_regist_infor_init(self):#自注册的数据部分
+ iccid = self.get_sim_iccid()
+ read_iccid = eventMesh.publish("get_iccid_data")
+ if read_iccid == None:
+ read_iccid = ""
+ url = get_report_url_website(None)#上报网址 根据需要更改上报网址
+ if iccid == -1:
+ iccid = str("FF")#为空就填写FF
+
+ IMSI = self.get_sim_imsi()
+ if IMSI == -1:#没有卡 则填FF
+ IMSI = str("FF")
+ imei = self.get_dev_imei()
+ if imei == -1:
+ imei = str("FF")
+
+ data_tmp = net.getCellInfo() #会适当卡个3-5s
+ i = 0
+ cell_data = 0
+ if(len(data_tmp) >= 1):
+ for cell in data_tmp:
+ if i == 2:#在list里面最多就三个元素 最后一个是LTE的数据
+ if cell != []:
+ for tup in cell:
+ print("tup:{}".format(tup))
+ if tup[0] == 0 and len(tup) > 0:#第0个代表当前服务的小区CELLID 7位16进制数
+ cell_data = tup[1]#这个是十进制数需要自行转换成十六进制数
+ print(cell_data)
+ break
+ i+=1
+ # cell_data = 0
+ cell_data = "%07x"%(cell_data)#7位16进制数不够前面补0
+ print(cell_data)
+ sendCellid = "{}".format(cell_data)
+ REGVER = "12.0"#当前数据域协议版本号
+ MODEL = "TXB-Watch Soar"#机型字段 -前面是厂商名 -后面是设备名
+ get_dev_version = eventMesh.publish("get_dev_version")#订阅消息
+ if get_dev_version == None:
+ get_dev_version = ""
+ SWVER = get_dev_version #软件版本号
+ UETYPE = "12"#终端类型 12是智能手表 11是儿童手表
+ SIM1ICCID = iccid
+ SIM1LTEIMSI = IMSI
+ MACID = ""#可用WALN的地址 终端布支持WLAN 就是不可上网
+ OSVER = "RTOS"#操作系统版本号
+ IMEI1 = imei#"876226002021717"#imei
+ SIM1CELLID = sendCellid#下发的小区ID
+ data = {
+ "REGVER":REGVER,
+ "MODEL":MODEL,
+ "SWVER":SWVER,
+ "UETYPE":UETYPE,
+ "SIM1ICCID":SIM1ICCID,
+ "SIM1LTEIMSI":IMSI,
+ "MACID":MACID,
+ "OSVER":OSVER,
+ "IMEI1":IMEI1,
+ "SIM1CELLID":SIM1CELLID,
+ "NETWORKTYPE":4
+ }
+ data_infor=ujson.dumps(data)#将字典转换成json格式
+ json_bytes = bytes(data_infor, 'utf-8')#转换成字节数
+ data_encode = base64.b64encode(json_bytes)#再转换成base64的编码格式 密文
+ print("data_infor:{} data:{}".format(data_encode,data))
+ headers_T = {'Content-Type':'application/encrypted-json'} #请求头信息 按照实际要求填写
+ request_result = 0
+ try:
+ response = request.post("http://zzhc.vnet.cn:9998/", data=data_encode,headers =headers_T)
+ request_result = 1
+ if response.status_code == 200 : #返回状态码 200服务器正常解析数据
+ content = response.content#后台返回的结果
+ c = next(content)
+
+ jsload_data = ujson.loads(c)
+ print("jsload_data:{}".format(ujson.loads(c))) #{"resultCode": "0","resultDesc": "Success"}
+ if "resultCode" in jsload_data or "resultDesc" in jsload_data:#返回结果码值
+ resultCode = jsload_data["resultCode"]#结果解析 "0" 成功 "1" 解码错误 "2" 校验错误
+ resultDesc = jsload_data["resultDesc"]#Success 表示自注册成功
+
+ if resultCode == "0" or resultDesc == "Success":#注册成功退出当前注册 保存当前的ICCID 不在进行自注册了
+ iccid = self.get_sim_iccid()#获取当前SIM的ICCID
+ if iccid != -1:#读到ICCID
+ self.timer_count = 0
+ self.check_timer.stop()
+ self.isRegistOk = 1#已完成自注册的标识
+ iccid_buf =str("ICCID:")+str(str(iccid))
+ eventMesh.publish("save_iccid_data",iccid_buf)
+ self.multiple_day_resend()
+ #上报成功后 需要29.5或者30.5天后重发 初始值为0.5也就是12小时 30天后再重发一次也是一个月后重发数据自注册域
+ print("regist success:!!!!!")
+ return 1
+ if resultCode == "1":
+ print("Decode error")#解码错误 设备编码不正确
+ return 0
+
+ if resultCode == "2":#
+ print("Check error")#校验错误 设备里面数据不正确 有些数据不应该为空
+ return 0
+
+ except Exception as e:
+ print("response:{}".format(e))
+ request_result = 0
+ return 0
+
+ def timer_cb(self,data):#定时器回调
+ self.telecom_regeist_infor()#重新进行自注册
+ pass
+ # 多日重发功能要求:
+ # 1) 多日重发是指:在重发周期 T 内,如果没有功能性触发数据域自注册(触发发送且发送成功),
+ # 则终端应根据当前终端实时信息组织数据域自注册(不能直接拿上一周期的内容不变而重发)内容
+ # 并发送的过程;
+ # 2) 多日重发的时间间隔周期 T 设置为 30 天;
+ # 3) 多日重发的过程应设置为:功能性(比如换卡等)触发数据域自注册后,立即启动定时器 t(t
+ # 的初始值应设为 0.5 天)开始重发计时,以后每当 t 时间等于 T 的整数倍(t=N*T)时,终端就进
+ # 行数据域自注册发送,发送后 t 不要清零不要初始化,只有当功能性触发数据域自注册后,t 才初
+ # 始化,t 的初始化值为 0.5 天。
+ # Multiple day resend
+ def multiple_day_resend(self):#多日重发机制函数 没有发送数据域或者发送成功
+
+ t = 12 #计时周期 按照0.5天 也就是12小时来计算
+ T = 30*24 #周期为30天 计算30天的总共小时数
+ # t = N*T#只有t为T的整数倍就需要重发数据域自注册
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)#获取时间戳
+ if self.multimer_init == 1:#已注册过或者开机5分钟之内没有注册 或者注册成功就开始出发多日重发机制
+ self.mulit_day_timesec = time_tmp+MULTI_DAY_RESEND_t#初始值多加12小时 #初始化t = 0.5天
+ REGIST_buf = str("REGIST:")+str(self.mulit_day_timesec)
+ eventMesh.publish("set_regist_time",REGIST_buf)
+ return
+ self.multimer_init = 1
+ #设置开始时间戳
+ get_timesec = eventMesh.publish("get_regist_time")#一开机初始化为0 没有保存过数据 如果保存过就用保存的时间
+ if get_timesec == 0:
+ self.mulit_day_timesec = time_tmp+MULTI_DAY_RESEND_t
+ REGIST_buf = str("REGIST:")+str(self.mulit_day_timesec)
+ eventMesh.publish("set_regist_time",REGIST_buf)
+ else:
+ self.mulit_day_timesec = get_timesec
+ self.multiDayResend_timer.start(60*60*1000,1,self.multiDayResendTimer_Cb)#一分钟计时
+
+ def multiDayResendTimer_Cb(self,*argc):#多日重发机制定时器回调函数
+ T = 30*24*60*60
+ date_tmp = utime.localtime()
+ time_tmp = utime.mktime(date_tmp)+MULTI_DAY_RESEND_t#获取时间戳
+
+ if time_tmp < self.mulit_day_timesec:#如果当前时间戳小于保存的时间戳
+ self.mulit_day_timesec = time_tmp
+ print("time_tmp: self.mulit_day_timesec:\r\n",time_tmp,self.mulit_day_timesec)
+
+ if time_tmp - self.mulit_day_timesec >= MULTI_DAY_RESEND_T:#一个周期的时间到了重发注册一次
+ network_state = eventMesh.publish("get_network_state")
+ print("get_network_state:\r\n",network_state)
+ if network_state == 0:#网络不正常就不需要重发了等下一个周期
+ return
+ result = self.telecom_regist_infor_init()#要自注册数据域信息发送完才初始化t
+ if result == 0: #上报出错了
+ return
+ self.mulit_day_timesec = time_tmp+MULTI_DAY_RESEND_t # 重发后 初始化t = 0.5天
+ REGIST_buf = str("REGIST:")+str(self.mulit_day_timesec)
+ eventMesh.publish("set_regist_time",REGIST_buf)
+
+
+ def set_telecom_init_state(self,event,msg):#开机5分钟内检查是否有联网 有一次联网就关闭检查
+ self.telecom_init_state = msg
+
+ def get_telecom_init_state(self,event,msg):
+ return self.telecom_init_state
+
+ def get_dmp_power_timer_count(self,event,msg):#开机后限定5分钟内完成自注册
+ return REGIST_POWER_ON_TIME
+
+ def get_dmp_power_num(self,event,msg):#开机限定次数最多十次 十次不成功就等下一次开机 或者多日重发机制
+ print("get_dmp_power_num:{}".format(self.timerPowerNum))
+ return self.timerPowerNum
+
+ def set_dmp_power_num(self,event,msg):
+ print("set_dmp_power_num:{}".format(msg))
+ self.timerPowerNum = msg
+ def clear_storage_data(self):
+ IFEXIST = ql_fs.path_exists("/usr/telecom_config.json") #不存在
+ if IFEXIST == True:
+ uos.remove("/usr/telecom_config.json")
+ isStorage = ql_fs.path_exists("/usr/china_mobie_config.json")#移动入库的配置文件移除
+ if isStorage == True:
+ uos.remove("/usr/china_mobie_config.json")
+ print("clear_storage_data;{} {}".format(IFEXIST,isStorage))
+
+
+ def telecom_dmp_power_on_init(self):#开机初始化一次检测
+ if eventMesh.publish("get_telecom_init_state") == 1:#发送消息获取对应的值
+ return
+ if eventMesh.publish("get_dmp_power_num") < (eventMesh.publish("get_dmp_power_timer_count")*1000)/30000:#开机检查
+ if eventMesh.publish("get_telecom_init_state") == 0:#开机初始化一次
+ status = eventMesh.publish("get_factory_status")
+ if status == None:
+ status = 0
+ if status == 0:#恢复出厂过需要清空存储数据
+ self.clear_storage_data()
+ pass
+ self.telecomTimer.start(1*1000,0,self.fun_cb)
+ eventMesh.publish("set_telecom_init_state",1)
+
+ def fun_cb(self,*argc):
+ self.telecom_regeist_infor()#开机初始一次自注册信息
+ pass
+ def telecom_dmp_power_on_count(self):#开机计时判断最多十次
+ if eventMesh.publish("get_telecom_init_state") != 1:#在开机五分钟之内只要一次联网正常就不需要再检查是否网络正常去自注册了
+ if eventMesh.publish("get_dmp_power_num") < (eventMesh.publish("get_dmp_power_timer_count")*1000)/30000:#10+1
+ num = eventMesh.publish("get_dmp_power_num") #开机计时 如果开机5分钟内没有一次网络正常的话 当前开机自注册不生效 等待下一次开机自注册触发 或者触发多日重发机制
+ num+=1
+ eventMesh.publish("set_dmp_power_num",num)#次数累计加一
+ else:
+ if self.power_on_multiflag == 1:
+ return
+ self.power_on_multiflag = 1
+ self.multiple_day_resend()
+ pass
+
+telecomDmpCb = telecomDmp()
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+import usocket
+import log
+import utime
+import slip
+import audio
+from machine import UART
+import _thread
+from queue import Queue
+from machine import Pin
+from machine import ExtInt
+import dataCall
+import voiceCall
+import net
+import osTimer
+import sim
+import modem
+import utime
+import checkNet
+import atcmd
+import ql_fs
+import pm
+import sms
+
+from usr.EventMesh import eventMesh
+
+log.basicConfig(level=log.INFO)
+clog = log.getLogger("cat1")
+
+CAT1_SERVICE_HEAD = 'FE'
+PROJECT_NAME = "Cat1SlipUDPService"
+PROJECT_VERSION = "PY_SRV_V17"
+CONFIG_JSON="/usr/system_config.json"
+CURRENT_APP_TYPE="pysrv"
+
+voiceCall.setVolume(10)
+lpm_fd = pm.create_wakelock("system_lock", len("system_lock"))
+pm.wakelock_lock(lpm_fd)
+telecomTimerCount = 0
+def get_versionkeyname_by_py(app_type):
+ return str("{}version".format(app_type))
+
+def get_default_versionvalue_by_py(app_type):
+ if (app_type == "pymain"):
+ return "PY_MAIN_V2"
+ elif (app_type == "pyota"):
+ return "PY_OTA_V14"
+ elif (app_type == "pysrv"):
+ return "PY_SRV_V16"
+
+if not ql_fs.path_exists(CONFIG_JSON):
+ data = {str(get_versionkeyname_by_py(CURRENT_APP_TYPE)):get_default_versionvalue_by_py(CURRENT_APP_TYPE)}
+ ql_fs.touch(CONFIG_JSON,data)
+
+def set_version_to_json_config(app_type,keyvalue):
+ try :
+ config_data = ql_fs.read_json(CONFIG_JSON)
+ config_data.update( {str(get_versionkeyname_by_py(app_type)):keyvalue})
+ ql_fs.touch(CONFIG_JSON, config_data)
+ except Exception as e:
+ clog.error("set_version_to_json_config")
+
+def get_version_from_json_config(app_type):
+ config_data = ql_fs.read_json(CONFIG_JSON)
+ keyvalue = config_data.get( get_versionkeyname_by_py(app_type),get_default_versionvalue_by_py(app_type))
+ return keyvalue
+
+set_version_to_json_config(CURRENT_APP_TYPE,PROJECT_VERSION)
+
+
+audio.set_qdai_cfg(1,0,0,1,0,0,1,1)
+def ExtIntfun(args):
+ if args[1] == 0:
+ pm.wakelock_lock(lpm_fd)
+ elif args[1] == 1:
+ pm.wakelock_unlock(lpm_fd)
+extint = ExtInt(ExtInt.GPIO22, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_DISABLE, ExtIntfun)
+extint.enable()
+
+gpioWakeBT = Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_DISABLE, 1)
+gpioWakeBT.set_dir(Pin.OUT)
+gpioWakeBT.write(0)
+
+UDP_CMD_GET_CAT1VER = '0'
+UDP_CMD_DIAL_NUMB = '1'
+UDP_CMD_HUNGUP = '2'
+UDP_CMD_ANSWER = '3'
+UDP_CMD_CAT1_OTA_UPDATE = '4'
+UDP_CMD_SEND_SMS = '5'
+UDP_CMD_GET_TIME = '6'
+UDP_CMD_GET_RECV_NETWORKSTAT = '7'
+UDP_MSG_SMS = '8'
+UDP_CMD_ATCMD = '9'
+UDP_MSG_CALL_CONNECTED = 'A'
+UDP_MSG_CALL_DISCONNECTED = 'B'
+UDP_MSG_COMMING_CALL = 'C'
+UDP_MSG_REPLY = 'F'
+
+class Cat1Service:
+ AP = 0
+ STA = 1
+ def __init__(self, uart=UART.UART4, mode=AP):
+ self.__uart = uart
+ self.__mode = mode
+ self.__message = ''
+ self.__err = 0
+ self.__net_connected = 0
+ self.__wait_resp = 0
+ self.__waiting_netstat = 0
+ slip.destroy()
+ ret = slip.construct(self.__uart, self.__mode, 0)
+ if ret != 0:
+ return None
+ self.__sock = self.__socket_init()
+ self.__threadid = _thread.start_new_thread(self.__Socket_Thread, ())
+ self.telecom_init_flag = 0
+ self.telecomTimer = osTimer()
+ eventMesh.subscribe("cat1_reply_iccid_to_ble",self.cat1_reply_iccid_to_ble)
+ eventMesh.subscribe("cat1_reply_timesec_to_ble",self.cat1_reply_timesec_to_ble)
+ self.iccid_data = ""
+ self.software_version = ""
+ self.deletSmsTimer = osTimer()
+ self.volte_switch = 1
+ eventMesh.subscribe("set_dmp_change_mode",self.set_dmp_change_mode)
+ eventMesh.subscribe("get_dmp_change_mode",self.get_dmp_change_mode)
+ eventMesh.subscribe("delete_sms_event",self.delete_sms_event)
+ eventMesh.subscribe("remove_all_sms_cb", self.remove_all_sms_cb)
+ eventMesh.subscribe("send_sms_max_to_Ble",self.send_sms_max_to_Ble)
+ eventMesh.subscribe("get_all_sms_data",self.get_all_sms_data)
+ eventMesh.subscribe("send_singal_data_toBle",self.send_singal_data_toBle)
+ eventMesh.subscribe("delete_sms_single_data",self.delete_sms_single_data)
+ eventMesh.subscribe("get_factory_status",self.get_factory_status)
+ eventMesh.subscribe("set_factory_status",self.set_factory_status)
+ eventMesh.subscribe("send_dmp_cm_address_toBLE",self.send_dmp_cm_address_toBLE)
+ eventMesh.subscribe("set_volte_switch",self.set_volte_switch)
+ eventMesh.subscribe("get_volte_switch",self.get_volte_switch)
+ eventMesh.publish("delete_sms_event")
+ self.telecom_dmp_switch = 0
+ self.send_data = []
+ self.code_old = 0
+ self.code_old_num = 1
+ self.tmp_data = []
+ self.total_num = 0
+ self.msg_nums = 0
+ self.msg_nums_old = 0
+ self.china_mobile_init = 0
+ self.factory_status = 0
+ self.send_data_q = Queue(100)
+ self.ack_sem=0
+ _thread.start_new_thread(self.Socket_SEND_Thread,())
+ return None
+
+ def __socket_init(self):
+ sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM, usocket.TCP_CUSTOMIZE_PORT)
+ sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1)
+ bind_addr = ('172.16.1.2', 5000)
+ sock.bind(bind_addr)
+ sock.settimeout(None)
+ return sock
+
+ def __socket_reinit(self):
+ return self.__socket_init()
+
+ def bootup_msg_to_bt(self):
+ modem_ver = modem.getDevFwVersion()
+ self.reply_cmd('0F',"BOOTUP@pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver))
+ self.reply_cmd('0F',"VOLUME:{}".format(voiceCall.getVolume()))
+
+ def btmcu_cmd_handler(self,cmd,parm):
+ if cmd == "00":
+ modem_ver = modem.getDevFwVersion()
+ self.reply_cmd('00',"pyVer:{}@modemVer:{}".format(PROJECT_VERSION,modem_ver))
+ elif cmd == "01":
+ if eventMesh.publish("get_volte_switch") == 1:
+ ret = voiceCall.callStart(str(parm))
+ if ret != 0:
+ self.reply_cmd('0F',"callcmd_fail")
+ else:
+ self.reply_cmd('0F',"callcmd_success")
+ else:
+ self.reply_cmd('0F',"callcmd_fail")
+ elif cmd == "02":
+ ret = voiceCall.callEnd()
+ if ret != 0:
+ ret = voiceCall.callEnd()
+ if ret != 0:
+ self.reply_cmd('0F',"callend_fail")
+ else:
+ self.reply_cmd('0F',"callend_success")
+ elif cmd == "03":
+ ret = voiceCall.callAnswer()
+ if ret != 0:
+ ret = voiceCall.callAnswer()
+ if ret != 0:
+ self.reply_cmd('0F',"callanswer_fail")
+ else:
+ self.reply_cmd('0F',"callanswer_success")
+ elif cmd == "06":
+ time=utime.localtime()
+ zone=utime.getTimeZone()
+ self.reply_cmd('06',"{0}@{1}".format(time,zone))
+ elif cmd == "07":
+ simstat = sim.getStatus()
+ imei = modem.getDevImei()
+ netstat = "0,10,0,10"
+ netstat_ = net.getState()
+ if netstat_ != -1 :
+ netstat = "{},{},{},{}".format(netstat_[0][0],netstat_[0][3],netstat_[1][0],netstat_[1][3])
+ operator = net.operatorName()
+ signal = net.csqQueryPoll()
+ self.reply_cmd('07',"imei:{0}@sim:{1}@oper:{2}@signal:{3}@net:{4}".format(imei,simstat,operator,signal,netstat))
+ elif cmd == "09":
+ resp=bytearray(50)
+ ret=atcmd.sendSync("{}\r\n".format(parm),resp,'',10)
+ if ret == 0:
+ self.reply_cmd('09',"{}".format(resp.decode()))
+ else:
+ self.reply_cmd('09',"{}".format("at error"))
+
+ elif cmd == "10" or cmd == "12" or cmd == "14":
+ if 1:
+ if eventMesh.publish("get_dmp_change_mode") == 1:
+ self.telecom_recv_cmd(cmd,parm)
+ else:
+ pass
+
+ if 1:
+ if eventMesh.publish("get_dmp_change_mode") > 1:
+ self.china_mobile_recv_cmd(cmd,parm)
+ else:
+ pass
+ pass
+ elif cmd == "13":
+ on = int(parm)
+ eventMesh.publish("set_dmp_change_mode",on)
+ elif cmd == "16":
+ if 1:
+ if eventMesh.publish("get_dmp_change_mode") > 1:
+ self.china_mobile_recv_cmd(cmd,parm)
+ else:
+ pass
+ elif cmd == "17":
+ eventMesh.publish("set_factory_status",int(parm))
+ elif cmd == "18":
+ eventMesh.publish("set_dmp_cm_address",str(parm))
+ elif cmd == "19":
+ voiceCall.startDtmf(str(parm),100)
+ elif cmd == "1A":
+ eventMesh.publish("set_volte_switch",int(parm))
+ elif cmd == "AC":
+ if self.ack_sem==1:
+ self.ack_sem=0
+
+ def telecom_recv_cmd(self,cmd,parm):
+ if cmd == "10":
+ self.software_version = str(parm)
+ eventMesh.publish("set_dev_version",self.software_version)
+ elif cmd == "12":
+ pass
+ elif cmd == "14":#
+ pass
+ pass
+
+ def set_volte_switch(self,event,msg):
+ self.volte_switch = int(msg)
+
+ def get_volte_switch(self,event,msg):
+ return self.volte_switch
+
+ def china_mobile_recv_cmd(self,cmd,parm):
+ if cmd == "10":
+ self.software_version = str(parm)
+ eventMesh.publish("set_dev_version",self.software_version)
+ elif cmd == "16":
+ eventMesh.publish("set_dev_mac",str(parm))
+ pass
+ def get_factory_status(self,event,msg):
+ return self.factory_status
+ def set_factory_status(self,event,msg):
+ self.factory_status = int(msg)
+ if self.factory_status == 0: #只有为的时候才设置进去 1不再设置
+ self.reply_cmd('17',"{}".format(1))
+
+ def send_dmp_cm_address_toBLE(self,event,msg):
+ buf_tmp = "address:"+str(msg)
+ self.reply_cmd('18',"{}".format(buf_tmp))
+
+ def set_dmp_change_mode(self,event,msg):
+ self.telecom_dmp_switch = msg
+ def delete_sms_single_data(self,event,msg): #删除单条信息
+ sms.deleteMsg(int(msg))
+
+ def get_dmp_change_mode(self,event,msg):
+ return self.telecom_dmp_switch
+ def delete_sms_event(self,event,msg):
+ self.deletSmsTimer.start(2*1000,0,self.delete_sms_cb)
+ def delete_sms_cb(self,*argc):
+ eventMesh.publish_async("remove_all_sms_cb","",1*1024)
+ def remove_all_sms_cb(self, event, msg):
+ msg_nums = sms.getMsgNums()
+ if msg_nums == -1:
+ msg_nums = 0
+ sms_data = sms.getSaveLoc()
+ if sms_data == -1:
+ return
+ sms_max = sms_data[0][2]
+ if sms_max >= msg_nums and sms_max > 0:
+ sms.deleteMsg(1,4)
+
+ def send_singal_data_toBle(self,event,msg):
+ msg_nums = sms.getMsgNums()
+ if msg_nums == -1:
+ msg_nums = 0
+ sms_data = sms.getSaveLoc()
+ if sms_data == -1:
+ return
+ sms_max = sms_data[0][2]
+ message=self.sms_get_message_info(int(msg))
+ if message == -1:
+ return
+ message_pdu = sms.decodePdu(message[5],20)
+ if message_pdu != -1:
+ message_ref = message[0]
+ message_total_num = message[1]
+ message_seq = message[2]
+ data = message[5]
+ data_len = len(data)
+ msg_total = "ref:"+str(message_ref)+"@total_num:"+str(message_total_num)+"@seq:"+str(message_seq)+"@data:"+str(message[5])
+ self.reply_cmd('15',msg_total)
+
+ eventMesh.publish("delete_sms_single_data",int(msg))
+
+ def sms_deal_phone_number(self,args):
+ data=enumerate(args)
+ data_str1=""
+ data_str2=""
+ data_str3=""
+ for index,value in data:
+ if index % 2 == 0:
+ data_str1=data_str1+value
+ else:
+ data_str2=data_str2+value
+ for i in range(0,len(data_str1)):
+ data_str3=data_str3+data_str2[i]
+ data_str3=data_str3+data_str1[i]
+ return data_str3
+ def sms_get_message_info(self,index):
+ message0=sms.searchPduMsg(index)
+ if message0 == -1:
+ return -1
+
+ sca_num = int(message0[0:2],16) - 1
+ data_len = 2
+ addr_type= message0[data_len:data_len+1*2]
+ data_len = data_len+1*2
+
+ sca = message0[data_len:data_len+sca_num*2]
+ sca = self.sms_deal_phone_number(sca)
+ data_len = data_len+sca_num*2
+
+ pdu_tye = int(message0[data_len:data_len+1*2],16)
+ data_len = data_len+1*2
+
+ oa_num = int(message0[data_len:data_len+1*2],16)
+ data_len = data_len+1*2
+ oa_addr_type = message0[data_len:data_len+1*2]
+ data_len = data_len+1*2
+
+ if oa_num % 2 == 1:
+ oa_num_t = int((oa_num + 1)/2)
+ else:
+ oa_num_t = int((oa_num )/2)
+
+ oa = message0[data_len:data_len+oa_num_t*2]
+ oa = self.sms_deal_phone_number(oa)
+ data_len = data_len+oa_num_t*2
+ pid = message0[data_len:data_len+1*2]
+
+ data_len = data_len+1*2
+ dcs = message0[data_len:data_len+1*2]
+ data_len = data_len+1*2
+ scts = message0[data_len:data_len+7*2]
+ data_len = data_len+7*2
+ sub_message_len = int(message0[data_len:data_len+1*2],16)
+ data_len = data_len+1*2
+ sub_message_head = message0[data_len:data_len+6*2]
+ data_len = data_len+6*2
+ sub_message_data = message0[data_len:data_len+sub_message_len*2]
+
+ if ((pdu_tye & 0x40 ) >> 6) == 1:
+ message_ref = int(sub_message_head[6:8],16)
+ message_total_num = int(sub_message_head[8:10],16)
+ message_seq = int(sub_message_head[10:12],16)
+ return [message_ref,message_total_num,message_seq,pdu_tye,sub_message_len,message0]
+ else:
+ return [0,1,1,pdu_tye,sub_message_len,message0]
+
+
+
+ def send_sms_max_to_Ble(self,event,msg):
+ msg_nums = sms.getMsgNums()
+ if msg_nums == -1:
+ msg_nums = 0
+ sms_data = sms.getSaveLoc()
+ if sms_data != -1:
+ sms_max = sms_data[0][2]
+ self.reply_cmd('15',"@sms_max:"+str(sms_max)+"@current_num:"+str(msg_nums))
+ pass
+
+ def get_all_sms_data(self,event,msg):
+ msg_total = ""
+ SMS_lis={}
+ SMS_lis_count = 0
+ sms_data = sms.getSaveLoc()
+ if sms_data == -1:
+ return
+ sms_max = sms_data[0][2]
+ self.msg_nums = sms.getMsgNums()
+ if self.msg_nums_old != self.msg_nums:
+ self.send_data = []
+ self.msg_nums_old = self.msg_nums
+ if self.send_data == [] :
+ for i in range(self.msg_nums):
+ phonenum = ""
+ data =""
+ time = ""
+ data_len = 0
+ message=self.sms_get_message_info(self.msg_nums-i-1)
+ if message == -1:
+ break
+ data = message[5]
+ sms_data = []
+ code = message[0]
+ num = message[1]
+ curren_num = message[2]
+ data_len = message[4]
+ sms_data.append(code)
+ sms_data.append(num)
+ sms_data.append(curren_num)
+ sms_data.append(data)
+ sms_data.append(data_len)
+ self.send_data.append(sms_data)
+ count = len(self.send_data)
+ for i in range(count):
+ text = self.send_data[i]
+ msg_total = "@code:"+str(text[0])+"@totalcodenum:"+str(text[1])+"@currcodeid:"+str(text[2])+"@data:"+str(text[3])
+ self.reply_cmd('17',msg_total)
+
+ def notifyIncomingcall(self, incomming_numb):
+ self.clear_remain()
+ __head = '0C'
+ __message = str(incomming_numb)
+ self.__Socket_UDP(__head, __message)
+ return 0
+
+ def notifyConnecteCall(self, phone_numb):
+ self.clear_remain()
+ __head = '0A'
+ __message = str(phone_numb)
+ self.__Socket_UDP(__head, __message)
+ return 0
+
+ def notifyDisconnectCall(self, phone_numb):
+ self.clear_remain()
+ __head = '0B'
+ __message = str(phone_numb)
+ self.__Socket_UDP(__head, __message)
+ return 0
+
+ def wait_network_ready(self):
+ if(self.__waiting_netstat == 1):
+ return 0
+ self.__waiting_netstat = 1
+ stage, state = checkNet.waitNetworkReady(30)
+ pm.wakelock_unlock(lpm_fd)
+ if stage == 3 and state == 1:
+ self.set_network_config()
+ self.__net_connected = 1
+ eventMesh.publish("set_network_state",self.__net_connected)
+ self.__waiting_netstat = 0
+ return 0
+ else:
+ self.reset_network_config()
+ self.__net_connected = 0
+ eventMesh.publish("set_network_state",self.__net_connected)
+ self.__waiting_netstat = 0
+ return -1
+
+ def timesync(self,_timesync):
+ self.clear_remain()
+ message = str(_timesync)
+ self.__Socket_UDP('0D', message)
+ return 0
+
+ def reply_timesync(self,_timesync):
+ self.clear_remain()
+ message = str(_timesync)
+ self.__Socket_UDP_noreply('0D', message)
+ return 0
+
+ def reply_cmd(self,cmd,_timesync):
+ try :
+ self.clear_remain()
+ message = str(_timesync)
+ self.__Socket_UDP_noreply(cmd, message)
+ except:
+ clog.info('reply_cmd')
+ return 0
+
+ def clear_remain(self):
+ self.__err = 0
+ def router_add(self, ip='192.168.4.1', mask='255.255.255.0'):
+ self.ip = ip
+ self.mask = mask
+ return slip.router_add(self.ip, self.mask)
+
+ def ipconfig(self):
+ return slip.ipconfig()
+
+ def set_dns(self, pri_dns='8.8.8.8', sec_dns='114.114.114.114'):
+ self.pri_dns = pri_dns
+ self.sec_dns = sec_dns
+ return slip.set_dns(self.pri_dns,self.sec_dns)
+
+ def set_default_NIC(self, ip_str):
+ self.ip_str = ip_str
+ return slip.set_default_netif(self.ip_str)
+
+ def reset_network_config(self):
+ if (self.__net_connected == 0):
+ return 0
+ Info = dataCall.getInfo(1,0)
+ default_NIC_ip = Info[2][2]
+ segment_ip = '172.16.4.0'
+ mask = '255.255.255.0'
+ cat1service.set_default_NIC(default_NIC_ip)
+ cat1service.router_add(segment_ip, mask)
+
+ pri_dns = '8.8.8.8'
+ sec_dns = '114.114.114.114'
+ cat1service.set_dns(pri_dns, sec_dns)
+ cat1service.ipconfig()
+
+ def set_network_config(self):
+ if (self.__net_connected == 1) :
+ return 0
+ Info = dataCall.getInfo(1,0)
+ default_NIC_ip = Info[2][2]
+ segment_ip = '172.16.1.0'
+ mask = '255.255.255.0'
+ cat1service.set_default_NIC(default_NIC_ip)
+ cat1service.router_add(segment_ip, mask)
+
+ pri_dns = '8.8.8.8'
+ sec_dns = '114.114.114.114'
+ cat1service.set_dns(pri_dns, sec_dns)
+ cat1service.ipconfig()
+ if eventMesh.publish("get_dmp_change_mode") == 0:
+ return
+ if 1:
+ if eventMesh.publish("get_dmp_change_mode") == 1:
+ eventMesh.publish("set_network_state",1)
+ if 1:
+ if eventMesh.publish("get_dmp_change_mode") > 1:
+ eventMesh.publish("set_network_state",1)
+ if self.china_mobile_init == 1:
+ return
+ self.china_mobile_init = 1
+
+ def cat1_reply_iccid_to_ble(self,event,msg):
+ ICCID_DATA = str("ICCID:")+str(msg)
+ self.reply_cmd('11',"{}".format(ICCID_DATA))
+ pass
+ def cat1_reply_timesec_to_ble(self,event,msg):
+
+ self.reply_cmd('14',"REGIST_TIME:{}".format(msg))
+ pass
+
+ def stop(self):
+ slip.destroy()
+ return 0
+
+ def __pack_tlv_format(self, head, content):
+ if len(content) == 0 or len(content) > 9999 or len(head) != 2:
+ return -1
+ len_str ='%04d' % len(content)
+ tlv_pack = CAT1_SERVICE_HEAD+head+len_str+content
+ return tlv_pack
+
+ def __unpack_tlv_format(self, msg):
+ self.msg = str(msg)[2:]
+ tag = self.msg[0:2]
+ length = self.msg[2:6]
+ value = self.msg[6:]
+ len_str ='%04d' % len(value)
+ if len(value) == 0 or len(value) > 9999 or len(tag) != 2 or len_str != self.msg[2:6]:
+ return -1
+ unpack = (tag,length,value)
+ return unpack
+ def __Socket_UDP(self, head, content):
+ self.send_data_q.put([head,content])
+ def Socket_SEND_Thread(self):
+ while True:
+ try:
+ data=self.send_data_q.get()
+ self.ack_sem=1
+ self.__Socket_UDP_write( data[0], data[1])
+ count=20
+
+ while count & self.ack_sem :
+ utime.sleep_ms(1)
+ count=count-1
+ self.__Socket_UDP_write( data[0], data[1])
+ except Exception :
+ clog.error("sned Socket >>>")
+
+ def __Socket_UDP_write(self, head, content):
+ try:
+ gpioWakeBT.write(1)
+ utime.sleep_ms(2)
+ gpioWakeBT.write(0)
+ utime.sleep_ms(20)
+ msg = self.__pack_tlv_format(head, content)
+ server_addr = ('172.16.1.5',1000)
+ self.__err = 0
+ self.__sock.sendto(msg,server_addr)
+ self.__wait_resp = 1
+ self.__wait_resp = 0
+ return 1
+ except Exception as error:
+ clog.error(error)
+ return 0
+
+ def __Socket_UDP_noreply(self, head, content):
+ self.send_data_q.put([head,content])
+
+ def __Socket_Thread(self):
+ while True:
+ try:
+ data=self.__sock.recv(1024)
+ if data:
+ value = self.__unpack_tlv_format(data.decode())
+ if value != -1:
+ if value[1] == 'FF':
+ self.btmcu_cmd_handler(value[0],value[2])
+ else:
+ self.btmcu_cmd_handler(value[0],value[2])
+ else:
+ clog.error("data error!!")
+ except Exception as recverr:
+ if "110" in str(recverr):
+ self.__err = 1
+ else:
+ utime.sleep(1)
+ self.__sock = self.__socket_reinit()
+cat1service = Cat1Service()
+
+def voice_callback(args):
+ if args[0] == 10:
+ if eventMesh.publish("get_volte_switch") == 0: #关闭VOLTE功能
+ voiceCall.callEnd()
+ else:
+ cat1service.notifyIncomingcall(args[6])
+ elif args[0] == 11:
+ if eventMesh.publish("get_volte_switch") == 1: #开启VOLTE功能
+ cat1service.notifyConnecteCall(args[6])
+ elif args[0] == 12:
+ if eventMesh.publish("get_volte_switch") == 1: #开启VOLTE功能
+ cat1service.notifyDisconnectCall(args[6])
+voiceCall.setCallback(voice_callback)
+def checknet_cb(arg):
+ _thread.start_new_thread(cat1service.wait_network_ready, ())
+timer = osTimer()
+timer.start(30000,1,checknet_cb)
+
+def bootupmsg_cb(arg):
+ cat1service.bootup_msg_to_bt()
+
+delaybootupmsg_timer = osTimer()
+delaybootupmsg_timer.start(1000,0,bootupmsg_cb)
+
+
+
--- /dev/null
+import log
+
+# 设置日志输出级别
+log.basicConfig(level=log.INFO)
+fota_log = log.getLogger("china_mobile")
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+import example
+import log
+from machine import UART
+
+# 设置日志输出级别
+log.basicConfig(level=log.INFO)
+# 设置输出到debug口
+uart = UART(UART.UART0, 115200, 8, 0, 1, 0)
+log.set_output(uart)
+clog = log.getLogger("cat1")
+
+main_flag = 1
+
+
+try:
+ example.exec('/usr/main_init.py')
+ clog.info("启动main_init成功!!!!!\r\n")
+except Exception as e:
+ main_flag = 0
+ clog.error("启动失败!!!!!\r\n".format(e))
+
+try:
+ example.exec('/usr/tcpserver.py')
+ clog.info("启动tcpserver成功!!!!!\r\n")
+except Exception as e:
+ clog.error("启动失败!!!!!\r\n".format(e))
+
--- /dev/null
+from misc import Power
+import usocket
+import log
+import utime
+from machine import UART
+import _thread
+from queue import Queue
+from machine import Pin
+from machine import ExtInt
+import osTimer
+import utime
+import ql_fs
+import binascii
+import ujson
+import uos
+
+
+log.basicConfig(level=log.INFO)
+clog = log.getLogger("cat1")
+
+USR_FILE_PATH = "/usr" #
+BAK_FILE_PATH = "{}/TmpPyFile".format(USR_FILE_PATH)
+BAK_FILE_TMP = "_bak"
+CAT1_SERVICE_HEAD = "FE"
+CAT1_FILE_DATA_HEAD = "FF"
+CAT1_REPLAY_STATE="00"
+CAT1_CREAT_DIR_FAILE= "01"
+CAT1_CREAT_DIR_OK= "02"
+CAT1_NO_REPLAY_OTA_OK= "03"
+CAT1_WRITE_FILE_SUCC= "04"
+CAT1_WRITE_FILE_ERROR = "05"
+CAT1_CRC_ERROR = "06"
+CAT1_SEND_HEAD_ERR = "07"
+CAT1_OTA_TIMEOUT_BLE_NO_REPLAY = "08"
+CAT1_CREAT_FILE_ERROR = "09"
+CAT1_CREAT_FILE_SUCC = "0A"
+CAT1_ALLPY_FILE_TRANSFER_END = "0B"
+CAT1_REPLAY_OTA_SUCC = "0C"
+CAT1_REPLAY_OTA_FALIE = "0D"
+CAT1_REPLAY_FILE_SIZE_OK = "0E"
+CAT1_REPLAY_FILE_SIZE_ERR = "0F"
+CAT1_REPLAY_OTA_END_FAILE = "10"
+CAT1_NEED_UPDATE_OTA = "11"
+CAT1_TCP_STOP_OTA = 0
+CAT1_TCP_START_OTA = 1
+CAT1_TCP_START_SEND_SINGLE_FILE_INFO= 2
+CAT1_TCP_START_SEND_FILE_DATA= 3
+CAT1_TCP_START_OTA_FAILE = 4
+CAT1_TCP_START_OTA_SUCC = 5
+CAT1_TCP_START_SEND_ALLFILE_FINESH = 6
+CAT1_TCP_SEND_SINGLE_FINESH = 7
+CAT1_TCP_START_ERROR_INFO = 255
+
+gpioWakeBT = Pin(Pin.GPIO21, Pin.OUT, Pin.PULL_DISABLE, 1)
+gpioWakeBT.set_dir(Pin.OUT)
+gpioWakeBT.write(0)
+FILE_TRANSFER_TIMEOUT=60
+class TcpServiceInit:
+ AP = 0
+ STA = 1
+
+ def __init__(self, uart=UART.UART4, mode=AP):
+ self.__uart = uart
+ self.__mode = mode
+ self.Cat1FileState = 0
+ self.Cat1FileReplayBle = 0
+ self.Cat1TimeCount = 0
+ self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT
+ self.Cat1FileTransTimer = osTimer()
+ self.Cat1OtaTimeOut = osTimer()
+ self.crc_err = 0
+ self.allPyRecvFlag = 0
+ self.ota_state =0
+ self.ota_bstate =0
+ self.fileNameTmp = ""
+ self.fileNameList = []
+ self.fileSizeList = []
+ self.fileSize = 0
+ self.updateTimer = osTimer()
+ self.updateTimerCount = 0
+ self.updateTimerFlag = 0
+ self.sock = None
+ self.bakFlag = "0"
+ self.conn= None
+ self.__sock_file = None
+ self.__sock_file = self.__socket_file_init()
+ self.__thread_file = _thread.start_new_thread(self.__Socket_File_Thread, ())
+ self.conn_thread=_thread.start_new_thread(self._client_conn_proc, ())
+
+ def __pack_tlv_format(self, head, content):
+ head1 = head
+ content1 = content
+ if len(content1) == 0 or len(content1) > 9999 or len(head1) != 2:
+ return -1
+ len_str ='%04d' % len(content1)
+ tlv_pack = CAT1_SERVICE_HEAD+head1+len_str+content1
+ return tlv_pack
+
+ def __unpack_tlv_format(self, msg):
+ msg_tmp = str(msg)[2:]
+ tag = msg_tmp[0:2]
+ length = msg_tmp[2:6]
+ value = msg_tmp[6:]
+ len_str ='%04d' % len(value)
+ if len(value) == 0 or len(value) > 9999 or len(tag) != 2 or len_str != msg_tmp[2:6]:
+ return -1
+ unpack = (tag,length,value)
+ return unpack
+
+ def __socket_file_init(self):
+ self.sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM, usocket.IPPROTO_TCP_SER)
+ self.sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1)
+ bind_addr = ('172.16.1.2', 5001)
+ self.sock.bind(bind_addr)
+ self.sock.listen(10)
+ return self.sock
+
+ def __Socket_TCP_file_noreply(self, head, content):
+ head1 = head
+ content1 = content
+ gpioWakeBT.write(1)
+ utime.sleep_ms(2)
+ gpioWakeBT.write(0)
+ utime.sleep_ms(20)
+ msg = self.__pack_tlv_format(head1,content1)
+ if msg == -1:
+ return 0
+ try:
+ self.conn.send(msg)
+ except Exception as e:
+ clog.info("self.__sock_file error {}".format(e))
+ return 0
+
+ def _client_conn_proc(self):
+ while True:
+ if self.conn==None:
+ utime.sleep_ms(20)
+ continue
+ try:
+ data = self.conn.recv(1024)
+ if not data:
+ clog.info("__Socket_File_Thread data null:\r\n")
+ else:
+ self.src_data(data.decode('uft-8'))
+ except:
+ self.conn.close()
+ break
+
+ def __Socket_File_Thread(self):
+ while True:
+ try :
+ cli_conn, cli_ip_addr, cli_port = self.__sock_file.accept()
+ self.conn=cli_conn
+ clog.info('[serveice] accept a client: %s, %s' % (cli_ip_addr, cli_port))
+ except :
+ utime.sleep_ms(20)
+
+ def cat1FileTimerCb(self,*argc):
+ clog.info("timer test\r\n")
+ if self.Cat1PyFileTimout > 0:
+ self.Cat1PyFileTimout-=1
+ if self.Cat1PyFileTimout == 0:
+ self.Cat1PyFileTimout = 0
+ self.Cat1FileState = 0
+ self.deleteTmpFile()
+ self.deleteUsrTmpFile()
+ self.__Socket_TCP_file_noreply(CAT1_OTA_TIMEOUT_BLE_NO_REPLAY,"ota error") #结束文件接收不完整的
+ self.Cat1FileTransTimer.stop()
+ pass
+
+ def crc_cal(self,msg):
+ bytes_data = msg.encode('utf-8')
+ hex_data = binascii.hexlify(bytes_data)
+ hex_data = hex_data.decode()
+ data = hex_data
+ crcValue = 0
+ j = 0
+ i = 0
+ json_state = 0
+ crcbuf = 0
+ data_len = len(str(data))
+ try:
+ if data_len % 2 != 0:
+ json_state = 0
+ return [json_state,crcbuf]
+ except Exception as e:
+ json_state = 0
+ for i in range(data_len):
+ if j >= data_len:
+ break
+ try:
+ decimal_number = int(str(data[j:j+2]), 16)
+ crcValue=crcValue+decimal_number
+ crcValue = crcValue&0xff
+ except Exception as e:
+ clog.info("crc_cal")
+ j+=2
+ crcbuf = crcValue%256
+ crcbuf = 256-crcbuf
+ crcbuf = crcbuf%256
+ return [json_state,"%02x"%(crcbuf)]
+ def deleteTmpFile(self):
+ tmp_dir = ql_fs.path_exists(BAK_FILE_PATH)
+ if tmp_dir == True:
+ ql_fs.rmdirs(BAK_FILE_PATH)
+
+ def deleteUsrTmpFile(self):
+ return
+
+ def src_data(self,data):
+ if self.updateTimerFlag == 0:
+ self.updateTimerFlag = 1
+ self.updateTimer.stop()
+ msg = ""
+ json_state = 0
+ try:
+ msg = ujson.loads(data)
+ json_state = 1
+ except Exception as e:
+ json_state = 0
+ if json_state == 0:
+ value = self.__unpack_tlv_format(data)
+ self.cmd_data(value[0],value[2])
+ return
+ else:
+ self.file_data(msg)
+ pass
+ def cmd_data(self,cmd,parm):
+ if cmd == "01":
+ self.bakFlag = str(parm)
+ pass
+ def file_data(self,msg):
+ if "Code" in msg:
+ Code = int(msg["Code"])
+ if Code == CAT1_TCP_STOP_OTA:
+ self.allPyRecvFlag = 0
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.deleteTmpFile()
+ self.deleteUsrTmpFile()
+ pass
+ elif Code == CAT1_TCP_START_OTA:
+ self.ota_state =0
+ self.ota_bstate =0
+ self.allPyRecvFlag = 0
+ self.fileNameList = []
+ self.fileSizeList = []
+ self.allPyRecvFlag = 0
+ self.Cat1FileState = 0
+ self.deleteUsrTmpFile()
+ self.Cat1OtaTimeOut.stop()
+ check_dir = ql_fs.path_exists(BAK_FILE_PATH)
+ mk_dir_state = 0
+ if check_dir == True:
+ try:
+ self.deleteTmpFile()
+ except Exception as e:
+ clog.info("移除失败\r\n")
+ check_dir = ql_fs.path_exists(BAK_FILE_PATH)
+ if check_dir == False:
+ try:
+ ql_fs.mkdirs(BAK_FILE_PATH)
+ mk_dir_state = 1
+ except Exception as e:
+ mk_dir_state = 0
+ else:
+ mk_dir_state = 1
+ if mk_dir_state == 0:
+ self.__Socket_TCP_file_noreply(CAT1_CREAT_DIR_FAILE,"creat dir error!")
+ else:
+ self.Cat1FileState = 1
+ self.fileNameList = []
+ self.fileSizeList = []
+ self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT
+ self.Cat1FileTransTimer.stop()
+ self.Cat1FileTransTimer.start(1000,1,self.cat1FileTimerCb)
+ self.__Socket_TCP_file_noreply(CAT1_CREAT_DIR_OK,"creat dir success!")
+
+ elif Code == CAT1_TCP_START_SEND_SINGLE_FILE_INFO and self.Cat1FileState == 1:
+ self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT
+ self.fileNameTmp = str(msg["fileName"])
+ self.fileSize = msg["fileSize"]
+ self.fileNameList = msg["fileNameList"]
+ path = "{}/{}".format(BAK_FILE_PATH,self.fileNameTmp)
+ check_touch = ql_fs.path_exists("{}/{}".format(BAK_FILE_PATH,self.fileNameTmp))
+ if check_touch == True:
+ try:
+ uos.remove("{}/{}".format(BAK_FILE_PATH,self.fileNameTmp))
+ except Exception as e:
+ clog.info("移除文件失败\r\n")
+ try:
+ with open(path,"w+") as fd:
+ fd.write("")
+ fd.close()
+ self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_SUCC,"1creat file or dir success!")
+ except Exception as e:
+ self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_ERROR,"1creat file or dir err!")
+ else:
+ try:
+ with open(path,"w+") as fd:
+ fd.write("")
+ fd.close()
+ self.crc_err = 0
+
+ self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_SUCC,"2creat file or dir success!")
+ except Exception as e:
+ self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_ERROR,"2creat file or dir err!")
+
+
+ elif Code == CAT1_TCP_START_SEND_FILE_DATA and self.Cat1FileState == 1:
+ self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT
+ if len(self.fileNameTmp) == 0:
+ return
+ data = msg["data"]
+ if len(data) == 0:
+ return
+ tmpdata = str(data)
+ head = tmpdata[0:2]
+ if head != CAT1_FILE_DATA_HEAD or len(tmpdata) <= 8:
+ clog.info("head {}\r\n".format(head))
+ self.__Socket_TCP_file_noreply(CAT1_SEND_HEAD_ERR,"head error!")
+ return
+ datalen = str(tmpdata[2:6])
+ datalen = int("0x" + datalen, 16)
+ data_buf = tmpdata[6:]
+ data_buf = data_buf[:-2]
+ crc = tmpdata[-2:]
+ if len(str(data_buf)) == 0 or len(str(data_buf)) != datalen:
+ self.__Socket_TCP_file_noreply(CAT1_WRITE_FILE_ERROR,"crc error or data null!")
+ return
+ data = str(data_buf)
+ path = "{}/{}".format(BAK_FILE_PATH,str(self.fileNameTmp))
+ try:
+ with open(path,"a") as fd:
+ fd.write(data)
+ fd.close()
+ self.__Socket_TCP_file_noreply(CAT1_WRITE_FILE_SUCC,"write file success!")
+
+ except Exception as e:
+ self.__Socket_TCP_file_noreply(CAT1_WRITE_FILE_ERROR,"write file error!")
+
+ elif Code == CAT1_TCP_START_OTA_FAILE and self.Cat1FileState == 1:
+ self.allPyRecvFlag = 0
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"OTA FAILE")
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.deleteTmpFile()
+ self.deleteUsrTmpFile()
+ pass
+ elif Code == CAT1_TCP_START_SEND_ALLFILE_FINESH and self.Cat1FileState == 1:
+ if self.bakFlag == "0":
+ if self.allPyRecvFlag == 1:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!")
+ else:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!")
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.Cat1OtaTimeOut.stop()
+ self.Cat1TimeCount = 0
+ self.ota_state = 1
+ self.allPyRecvFlag = 1
+ self.Cat1OtaTimeOut.start(5000,0,self.otaTimeOut)
+ return
+ tmp_dir = ql_fs.path_exists(BAK_FILE_PATH)
+ if tmp_dir == True:
+ filenamesList = uos.listdir(BAK_FILE_PATH)
+ list1 = sorted(filenamesList)
+ list2 = sorted(self.fileNameList)
+ if list1 != list2:
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.deleteUsrTmpFile()
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!")
+ return
+ try:
+ copy_state = 1
+ compare_flag = 1
+ copy_flag = 0
+ filenamesList = uos.listdir(BAK_FILE_PATH)
+ for tmp in filenamesList:
+ dst_path = "{}/{}".format(USR_FILE_PATH,tmp)
+ src_path = "{}/{}".format(BAK_FILE_PATH,tmp)
+ ret = False
+ file_size = 0
+ try:
+ ret = ql_fs.file_copy(dst_path,src_path)
+
+ if ret == True:
+ dstfile_size = ql_fs.path_getsize(dst_path)
+ srcfile_size = ql_fs.path_getsize(src_path)
+ if dstfile_size != srcfile_size:
+ compare_flag = 0
+ break
+ else:
+ try:
+ compare_flag = 1
+ uos.remove(src_path)
+ filenamesList = uos.listdir(BAK_FILE_PATH)
+ except Exception as e:
+ clog.info("copy file \r\n")
+ else:
+ compare_flag = 0
+ break
+ except Exception as e:
+ clog.info("copy file \r\n")
+
+ if copy_state == 0 or compare_flag == 0 :
+ self.deleteUsrTmpFile()
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota faile!22")
+ return
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!")
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.Cat1OtaTimeOut.stop()
+ self.Cat1TimeCount = 0
+ self.ota_state = 1
+ self.allPyRecvFlag = 1
+ self.Cat1OtaTimeOut.start(5000,0,self.otaTimeOut)
+ except Exception as e:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota faile!33")
+ self.deleteUsrTmpFile()
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ else:
+ if self.ota_state == 1:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!")
+ pass
+ else:
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.deleteUsrTmpFile()
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!")
+
+ elif Code == CAT1_TCP_START_OTA_SUCC and self.Cat1FileState == 1:
+ if self.bakFlag == "0":
+ self.deleteUsrTmpFile()
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ if self.allPyRecvFlag == 1:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!")
+ else:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!")
+ return
+
+ if self.allPyRecvFlag == 0:
+ self.deleteTmpFile()
+ self.deleteUsrTmpFile()
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!")
+ return
+ tmp_dir = ql_fs.path_exists(BAK_FILE_PATH)
+ if tmp_dir == True:
+ filenamesList = uos.listdir(BAK_FILE_PATH)
+ list1 = sorted(filenamesList)
+ list2 = sorted(self.fileNameList)
+ if list1 != list2:
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.deleteUsrTmpFile()
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!")
+ return
+
+ try:
+ copy_state = 1
+ compare_flag = 1
+ filenamesList = uos.listdir(BAK_FILE_PATH)
+ for tmp in filenamesList:
+ dst_path = "{}/{}".format(USR_FILE_PATH,tmp)
+ src_path = "{}/{}".format(BAK_FILE_PATH,tmp)
+ ret = False
+ file_size = 0
+ try:
+ ret = ql_fs.file_copy(dst_path,src_path)
+ if ret == True:
+ dstfile_size = ql_fs.path_getsize(dst_path)
+ srcfile_size = ql_fs.path_getsize(src_path)
+ if dstfile_size != srcfile_size:
+ compare_flag = 0
+ break
+ else:
+ try:
+ compare_flag = 1
+ uos.remove(src_path)
+ filenamesList = uos.listdir(BAK_FILE_PATH)
+ except Exception as e:
+ clog.info("file\r\n")
+ else:
+ compare_flag = 0
+ break
+
+ except Exception as e:
+ clog.info("file\r\n")
+ if copy_state == 0 or compare_flag == 0 :
+ self.deleteUsrTmpFile()
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota faile!22")
+ return
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!")
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.Cat1OtaTimeOut.stop()
+ self.Cat1TimeCount = 0
+ self.ota_bstate = 1
+ self.conn.close()
+ self.Cat1OtaTimeOut.start(10000,0,self.otaTimeOut)
+ except Exception as e:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota faile!33")
+ self.deleteUsrTmpFile()
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ else:
+ if self.ota_bstate == 1:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"ota success!")
+ pass
+ else:
+ self.deleteTmpFile()
+ self.Cat1FileState = 0
+ self.Cat1FileTransTimer.stop()
+ self.deleteUsrTmpFile()
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_FALIE,"ota end faile!")
+
+ elif Code == CAT1_TCP_SEND_SINGLE_FINESH and self.Cat1FileState == 1:
+ self.Cat1PyFileTimout = FILE_TRANSFER_TIMEOUT
+ tmp_dir = ql_fs.path_exists(BAK_FILE_PATH)
+ if tmp_dir == True:
+ tmp_file = ql_fs.path_exists("{}/{}".format(BAK_FILE_PATH,self.fileNameTmp))
+ if tmp_file == True:
+ file_size = ql_fs.path_getsize("{}/{}".format(BAK_FILE_PATH,self.fileNameTmp))
+ if self.fileSize != file_size:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_ERR,"file size err")
+ else:
+ if self.bakFlag == "0":
+ dst_path = "{}/{}".format(USR_FILE_PATH,self.fileNameTmp)
+ src_path = "{}/{}".format(BAK_FILE_PATH,self.fileNameTmp)
+ ret = False
+ try:
+ ret = ql_fs.file_copy(dst_path,src_path)
+ if ret == True:
+ dstfile_size = ql_fs.path_getsize(dst_path)
+ srcfile_size = ql_fs.path_getsize(src_path)
+ if dstfile_size != srcfile_size:
+ src_file = ql_fs.path_exists(src_path)
+ if src_file == True:
+ try:
+ uos.remove(src_path)
+ except Exception as e:
+ clog.info("copy 文件异常出错 yichu!{}:\r\n".format(e))
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_ERR,"file size err")
+ return
+ else:
+ src_file = ql_fs.path_exists(src_path)
+ if src_file == True:
+ try:
+ uos.remove(src_path)
+ except Exception as e:
+ clog.info("copy 文件异常出错!!!!!!!!!!{}:\r\n".format(e))
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_OK,"file size ok")
+ return
+ else:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_ERR,"file copy err")
+ except Exception as e:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_ERR,"file copy err")
+ else:
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_FILE_SIZE_OK,"file copy ok")
+ else:
+ self.__Socket_TCP_file_noreply(CAT1_CREAT_FILE_ERROR,"creat file or dir err!")
+ pass
+ else:
+ self.__Socket_TCP_file_noreply(CAT1_CREAT_DIR_FAILE,"creat file or dir error!")
+ pass
+ else:
+ if self.Cat1FileState == 0:
+ if self.Cat1FileReplayBle == 1:
+ return
+ self.Cat1FileReplayBle = 1
+ self.__Socket_TCP_file_noreply(CAT1_REPLAY_OTA_SUCC,"reset start!")
+ self.Cat1FileState == 0
+ self.Cat1FileTransTimer.stop()
+ self.Cat1PyFileTimout = 0
+ self.fileNameList=[]
+ self.deleteTmpFile()
+ self.deleteUsrTmpFile()
+
+ def otaTimeOut(self,*argc):
+ clog.info("重启成功!!!!!!!!\r\n")
+
+TcpService = TcpServiceInit()
+
+
--- /dev/null
+import log
+
+# 设置日志输出级别
+log.basicConfig(level=log.INFO)
+fota_log = log.getLogger("telecom_dmp")
--- /dev/null
+this is test2 file
\ No newline at end of file
--- /dev/null
+Óû§Êý¾Ý·¾¶
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import time
+import struct
+import shutil
+
+"""
+介绍:
+ 本脚本主要实现调用mkyaffs2image工具生成文件镜像
+ 请注意使用本脚本时支持的python版本,本脚本只支持python3版本。
+ 请根据实际情况配置对应信息,主要是nandflash的信息,以及分区信息
+
+"""
+
+root_path = os.path.join(os.path.split(os.path.realpath(__file__))[0], '..', '..', '..', '..', '..', '..')
+cur_dir = os.path.dirname(os.path.abspath(__file__))
+image_tool_path = os.path.realpath(os.path.join(root_path, 'tools', 'bin', 'platform_tool', 'mkyaffs2image'))
+
+# 配置生成文件镜像工具路径
+mkyaffstool = os.path.join(image_tool_path, 'mkyaffs2image')
+image_name = "file"
+
+# 配置nandflash信息
+cfg_page_size = 2048
+cfg_obb_size = 64
+single_user_partition = True
+# 配置分区信息,请根据实际情况进行配置,添加格式为[分区路径, 分区大小]
+# 分区大小需要根据按照百分系统分配好后的blocks数进行计算,大小=blocks(文件块个数)*pages_per_block(每个文件块包含的页数)*bytes_per_page(每页包含字节数)
+# 前面按照比例分好分区,最后分区置成null,即代表剩下所有blocks
+# drivers/drivers/driver/nand_flash/nand/nandflash_config.c
+# #ifndef MEMORY_MINI
+# #define YF_NAME_STRS "/user/system/", "/user/update/", "/user/music/", "/user/"
+# uint32_t yf_volume_percent[YF_VOLUMES_NUM] = { 1, 1, 1, 97 };
+# 0x140000
+# 10 10 10 70
+# 0xcc0000
+
+partition_list = [
+ [os.path.join(cur_dir, 'fs', 'system'), "0xcc0000"],
+ [os.path.join(cur_dir, 'fs', 'update'), "0xcc0000"],
+ [os.path.join(cur_dir, 'fs', 'music'), "0xcc0000"],
+ [os.path.join(cur_dir, 'fs', 'user'), "null"]
+ ]
+
+partition_list_single = [
+ [os.path.join(cur_dir, 'fs', 'user'), "null"]
+ ]
+
+# 将生成image文件转换大小端,保存成另外文件
+def convert(src_file, dest_file):
+ fp_src = open(src_file, 'rb')
+ fp_dest = open(dest_file, 'wb')
+ src_size = os.path.getsize(src_file)
+ for i in range(int(src_size / 4)):
+ data = fp_src.read(4)
+ rw = struct.pack('BBBB', data[3], data[2], data[1], data[0])
+ fp_dest.write(rw)
+ fp_src.close()
+ fp_dest.close()
+
+def get_page_type(page_size):
+ if page_size == 2048:
+ return " 1"
+ elif page_size == 4096:
+ return " 2"
+ else:
+ return " 0"
+
+def get_obb_type(obb_size):
+ if obb_size == 64:
+ return " 2"
+ elif obb_size == 128:
+ return " 4"
+ else:
+ return " 0"
+
+if __name__ == "__main__":
+ image_file = os.path.join(cur_dir, "%s.bin" %image_name)
+ tmp_file = os.path.join(cur_dir, "%s_tmp.bin" %image_name)
+ if len(sys.argv) == 4 :
+ out_path = os.path.join(sys.argv[1], "%s.bin" %image_name)
+ if sys.argv[2] == '128' :
+ cfg_obb_size = 128
+ if sys.argv[3] == 'False':
+ single_user_partition = False
+ else:
+ print("need give parms output path and oobsize!")
+ sys.exit(1)
+
+ print("=========== oobsize {} single_user_partition {}".format(cfg_obb_size,single_user_partition))
+ if sys.platform == 'linux2' or sys.platform == 'linux':
+ partition_total = 0
+ page_type = get_page_type(cfg_page_size)
+ obb_type = get_obb_type(cfg_obb_size)
+
+ if os.path.exists(tmp_file):
+ os.remove(tmp_file)
+ if os.path.exists(image_file):
+ os.remove(image_file)
+ if single_user_partition :
+ for partition in partition_list_single:
+ if (partition[1] != "null"):
+ partition_total = partition_total + int(partition[1][2:], 16)
+ command = mkyaffstool + " " + partition[0] + " " + tmp_file + page_type + obb_type + (" 0x%x" %partition_total)
+ else:
+ command = mkyaffstool + " " + partition[0] + " " + tmp_file + page_type + obb_type
+ print(command)
+ os.system(command)
+ else:
+ for partition in partition_list:
+ if (partition[1] != "null"):
+ partition_total = partition_total + int(partition[1][2:], 16)
+ command = mkyaffstool + " " + partition[0] + " " + tmp_file + page_type + obb_type + (" 0x%x" %partition_total)
+ else:
+ command = mkyaffstool + " " + partition[0] + " " + tmp_file + page_type + obb_type
+ print(command)
+ os.system(command)
+ convert(tmp_file, image_file)
+
+ if os.path.exists(image_file):
+ shutil.copyfile(image_file, out_path)
+
+ print("make yaffs image file over!")
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import time
+import struct
+import shutil
+
+"""
+介绍:
+ 本脚本主要实现调用mkyaffs2image工具生成文件镜像
+ 请注意使用本脚本时支持的python版本,本脚本只支持python3版本。
+ 请根据实际情况配置对应信息,主要是nandflash的信息,以及分区信息
+
+"""
+
+root_path = os.path.join(os.path.split(os.path.realpath(__file__))[0], '..', '..', '..', '..', '..', '..')
+cur_dir = os.path.dirname(os.path.abspath(__file__))
+image_tool_path = os.path.realpath(os.path.join(root_path, 'tools', 'bin', 'platform_tool', 'unyaffs'))
+
+# 配置生成文件镜像工具路径
+mkyaffstool = os.path.join(image_tool_path, 'unyaffs')
+image_name = "file"
+
+# 配置nandflash信息
+cfg_page_size = 2048
+cfg_obb_size = 64
+
+
+#code/sdk/tools/bin/platform_tool/mkyaffs2image/mkyaffs2image code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/system code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/file_tmp.bin 1 2 0xcc0000
+#code/sdk/tools/bin/platform_tool/mkyaffs2image/mkyaffs2image code/sdk/build/config/target_config/brandy/mk_fs_image/fs/update code/sdk/build/config/target_config/brandy/mk_fs_image/file_tmp.bin 1 2 0x1980000
+#code/sdk/tools/bin/platform_tool/mkyaffs2image/mkyaffs2image code/sdk/build/config/target_config/brandy/mk_fs_image/fs/music code/sdk/build/config/target_config/brandy/mk_fs_image/file_tmp.bin 1 2 0x2640000
+#code/sdk/tools/bin/platform_tool/mkyaffs2image/mkyaffs2image code/sdk/build/config/target_config/brandy/mk_fs_image/fs/user code/sdk/build/config/target_config/brandy/mk_fs_image/file_tmp.bin 1 2
+# pagesize 2048 oobsize 64
+# 配置分区信息,请根据实际情况进行配置,添加格式为[分区路径, 分区大小]
+# 分区大小需要根据按照百分系统分配好后的blocks数进行计算,大小=blocks(文件块个数)*pages_per_block(每个文件块包含的页数)*bytes_per_page(每页包含字节数)
+# 前面按照比例分好分区,最后分区置成null,即代表剩下所有blocks
+# drivers/drivers/driver/nand_flash/nand/nandflash_config.c
+# #ifndef MEMORY_MINI
+# #define YF_NAME_STRS "/system/", "/update/", "/music/", "/user/"
+# uint32_t yf_volume_percent[YF_VOLUMES_NUM] = { 1, 1, 1, 97 };
+# 0x140000
+# 10 10 10 70
+# 0xcc0000
+
+
+partition_list = [
+ ["system","0x0", "0xcc0000"],
+ ["update","0xcc0000","0xcc0000"],
+ ["music", "0x1980000","0xcc0000"],
+ ["user", "0x2640000","null"]
+]
+
+# 将生成image文件转换大小端,保存成另外文件
+def convert(src_file, dest_file):
+ fp_src = open(src_file, 'rb')
+ fp_dest = open(dest_file, 'wb')
+ src_size = os.path.getsize(src_file)
+ for i in range(int(src_size / 4)):
+ data = fp_src.read(4)
+ rw = struct.pack('BBBB', data[3], data[2], data[1], data[0])
+ fp_dest.write(rw)
+ fp_src.close()
+ fp_dest.close()
+
+def splitimg(src_file,dest_file,startaddr,imgsize):
+ fp_src = open(src_file, 'rb')
+ fp_dest = open(dest_file, 'wb')
+ src_size = os.path.getsize(src_file)
+ print("{} {} {} {}".format(src_file,dest_file,startaddr,imgsize))
+ for i in range(int(src_size / 4)):
+ data = fp_src.read(4)
+ if i*4 >= startaddr and i*4 < (startaddr+imgsize):
+ # print(" write {} size {}".format(i*4,readsize))
+ rw = struct.pack('BBBB', data[3], data[2], data[1], data[0])
+ fp_dest.write(rw)
+ fp_src.close()
+ fp_dest.close()
+def split_img(src_file):
+ fileindex = 0
+ fp_src = open(src_file, 'rb')
+ dest_file = os.path.join(cur_dir, "%d_tmp.bin" %fileindex)
+ src_size = os.path.getsize(src_file)
+ fp_dest = open(dest_file, 'wb')
+ yaffsheader = struct.pack('BBBB', 0x59,0x46, 0x53, 0x53)
+ print("read {} ".format(yaffsheader))
+ for i in range(int(src_size / 4)):
+ data = fp_src.read(4)
+ rw = struct.pack('BBBB', data[3], data[2], data[1], data[0])
+ if data[0]==0x53 and data[1]==0x53 and data[2]==0x46 and data[3]==0x59:
+ # if data[0]==0x59 and data[1]==0x46 and data[2]==0x53 and data[3]==0x53:
+ if fileindex >= 0 :
+ fp_dest.close()
+ print("write {} size {}".format(dest_file,os.path.getsize(dest_file)))
+ dest_file = os.path.join(cur_dir, "%d_tmp.bin" %fileindex)
+ fp_dest = open(dest_file, 'wb')
+ fileindex+=1
+ fp_dest.write(rw)
+ fp_src.close()
+ fp_dest.close()
+
+
+def get_page_type(page_size):
+ if page_size == 2048:
+ return " 1"
+ elif page_size == 4096:
+ return " 2"
+ else:
+ return " 0"
+
+def get_obb_type(obb_size):
+ if obb_size == 64:
+ return " 2"
+ elif obb_size == 128:
+ return " 4"
+ else:
+ return " 0"
+
+if __name__ == "__main__":
+ image_file = os.path.join(cur_dir, "file.bin")
+
+ if sys.platform == 'linux2' or sys.platform == 'linux':
+ partition_total = 0
+ # page_type = get_page_type(cfg_page_size)
+ # obb_type = get_obb_type(cfg_obb_size)
+ page_type = " 1"
+ obb_type = " 2"
+
+ # if os.path.exists(tmp_file):
+ # os.remove(tmp_file)
+ # if os.path.exists(image_file):
+ # os.remove(image_file)
+ imgfilesize = os.path.getsize(image_file)
+
+ split_img(image_file)
+ # for partition in partition_list:
+ # tmp_file = os.path.join(cur_dir, "%s_tmp.bin" %partition[0])
+ # if (partition[2] != "null"):
+ # partition_total = partition_total + int(partition[2][2:], 16)
+ # splitimg(image_file,tmp_file,int(partition[1][2:], 16),int(partition[2][2:], 16))
+ # else:
+ # splitimg(image_file,tmp_file,int(partition[1][2:], 16), (imgfilesize - partition_total ))
+
+
+ # os.system(command)
+ # convert(tmp_file, image_file)
+ #unyaffs V0.9.7 - extract files from a YAFFS2 file system image.
+
+ # Usage: unyaffs [options] <image_file_name> [<extract_directory>]
+
+ # Options:
+ # -d detection of flash layout, no extraction
+ # -b spare contains bad block information
+ # -c <chunk size> set chunk size in KByte (default: autodetect, max: 16)
+ # -s <spare size> set spare size in Byte (default: autodetect, max: 512)
+ # -t list image contents
+ # -v verbose output
+ # -V print version
+
+ # unyaffs -c 2 -s 64 -b -t system_tmp.bin
+
+ # if (len(sys.argv) == 2 and os.path.exists(image_file)):
+ # out_path = os.path.join(sys.argv[1], "%s.bin" %image_name)
+ # shutil.copyfile(image_file, out_path)
+
+ print("make yaffs image file over!")