Skip to content

Commit 91aaf90

Browse files
authored
[FlashScript] Logging tweaks (#396)
* [FlashScript] add file logging, -v=0 is to screen, -v=1 is to file. * [FlashScript] tweak help text. * [FlashScript] add some debug info. * [FlashScript] change logging 0=info, 1=debug, add --log-file {LOG_FILENAME} * [FlashScript] update shelly_model, add Shelly Sensor1, remove not needed variables. * [FlashScript] fix log filename reporting.. * [FlashScript] fix log filename reporting.. * [FlashScript] fix file logging.. * [FlashScript] add --verbose levels 0 - 5 * [FlashScript] revert some warning messages, as the are not wanted, during flashing. * [FlashScript] make successful message lowest level so it always shows ``` ./flash-shelly.py -v=2 shelly1l-84CCA8ADF044 Do you wish to flash shelly1l-84CCA8ADF044 to firmware version 2.7.1 (y/n) ? y Successfully flashed shelly1l-84CCA8ADF044 to 2.7.1 ``` * [FlashScript] tweak debug info. * [FlashScript] tweak debug info. * [FlashScript] add 'flashed_devices' count, tweak debug. * [FlashScript] update help info in header. * [FlashScript] update help info in header. * [FlashScript] simply set level. * [FlashScript] log_level, use MAP variable instead of function. * [FlashScript] tweak debug info.
1 parent a1044b9 commit 91aaf90

File tree

1 file changed

+92
-61
lines changed

1 file changed

+92
-61
lines changed

tools/flash-shelly.py

Lines changed: 92 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
# or any other firmware please follow instructions here:
2222
# https://github.com/mongoose-os-apps/shelly-homekit/wiki
2323
#
24-
# usage: flash-shelly.py [-h] [-m {homekit,keep,revert}] [-a] [-q] [-l] [-e [EXCLUDE ...]] [-n] [-y] [-V VERSION] [-c HAP_SETUP_CODE] [--variant VARIANT] [-v {0,1}] [hosts ...]
24+
# usage: flash-shelly.py [-h] [-m {homekit,keep,revert}] [-a] [-q] [-l] [-e [EXCLUDE ...]] [-n] [-y] [-V VERSION] [-c HAP_SETUP_CODE] [-v {0,1,2,3,4,5}] [--variant VARIANT] [--log-file LOG_FILENAME]
25+
# [hosts ...]
2526
#
2627
# Shelly HomeKit flashing script utility
2728
#
@@ -43,9 +44,11 @@
4344
# Force a particular version.
4445
# -c HAP_SETUP_CODE, --hap-setup-code HAP_SETUP_CODE
4546
# Configure HomeKit setup code, after flashing.
47+
# -v {0,1,2,3,4,5}, --verbose {0,1,2,3,4,5}
48+
# Enable verbose logging 0=critical, 1=error, 2=warning, 3=info, 4=debug, 5=trace.
4649
# --variant VARIANT Prerelease variant name.
47-
# -v {0,1}, --verbose {0,1}
48-
# Enable verbose logging level.
50+
# --log-file LOG_FILENAME
51+
# Create output log file with chosen filename.
4952

5053

5154
import argparse
@@ -64,29 +67,18 @@
6467
logging.addLevelName(logging.TRACE, 'TRACE')
6568
logging.Logger.trace = functools.partialmethod(logging.Logger.log, logging.TRACE)
6669
logging.trace = functools.partial(logging.log, logging.TRACE)
67-
logging.basicConfig(format='%(message)s')
6870
logger = logging.getLogger(__name__)
69-
logger.setLevel(logging.INFO)
71+
logger.setLevel(logging.TRACE)
72+
log_level = {'0' : logging.CRITICAL,
73+
'1' : logging.ERROR,
74+
'2' : logging.WARNING,
75+
'3' : logging.INFO,
76+
'4' : logging.DEBUG,
77+
'5' : logging.TRACE}
7078

7179
upgradeable_devices = 0
80+
flashed_devices = 0
7281
arch = platform.system()
73-
# Windows does not support acsii colours
74-
if not arch.startswith('Win'):
75-
WHITE = '\033[1m'
76-
RED = '\033[1;91m'
77-
GREEN = '\033[1;92m'
78-
YELLOW = '\033[1;93m'
79-
BLUE = '\033[1;94m'
80-
PURPLE = '\033[1;95m'
81-
NC = '\033[0m'
82-
else:
83-
WHITE = ''
84-
RED = ''
85-
GREEN = ''
86-
YELLOW = ''
87-
BLUE = ''
88-
PURPLE = ''
89-
NC = ''
9082

9183
def upgrade_pip():
9284
logger.info("Updating pip...")
@@ -112,6 +104,7 @@ def __init__(self):
112104
self.queue = queue.Queue()
113105

114106
def add_service(self, zeroconf, type, device):
107+
logger.trace(f"[Device Scan] found device: {device}")
115108
device = device.replace('._http._tcp.local.', '')
116109
self.queue.put(Device(device))
117110

@@ -139,16 +132,16 @@ def is_valid_hostname(self, hostname):
139132
result = False
140133
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
141134
result = all(allowed.match(x) for x in hostname.split("."))
142-
logger.trace(f"Valid Hostname: {hostname} {result}")
135+
logger.debug(f"Valid Hostname: {hostname} {result}")
143136
return result
144137

145138
def is_host_online(self, host):
146139
try:
147140
self.wifi_ip = socket.gethostbyname(host)
148-
logger.trace(f"Hostname: {host} is Online")
141+
logger.debug(f"Hostname: {host} is Online")
149142
return True
150143
except:
151-
logger.warning(f"\n{RED}Could not resolve host: {host}{NC}")
144+
logger.error(f"\n{RED}Could not resolve host: {host}{NC}")
152145
return False
153146

154147
def get_device_url(self):
@@ -178,7 +171,7 @@ def get_device_info(self):
178171
except requests.exceptions.RequestException as err:
179172
logger.debug(f"Error: {err}")
180173
else:
181-
logger.debug(f"{RED}Could not get info from device: {self.host}\n{NC}")
174+
logger.debug(f"Could not get info from device: {self.host}")
182175
self.info = info
183176
return info
184177

@@ -226,14 +219,12 @@ def shelly_model(self, type):
226219
'SHGS-1' : 'ShellyGas',
227220
'SHEM' : 'ShellyEM',
228221
'SHEM-3' : 'Shelly3EM',
222+
'SHSEN-1' : 'ShellySensor1',
229223
'switch1' : 'Shelly1',
230224
'switch1pm' : 'Shelly1PM',
231225
'switch2' : 'Shelly2',
232226
'switch25' : 'Shelly25',
233227
'shelly-plug-s' : 'ShellyPlugS',
234-
'dimmer1' : 'ShellyDimmer1',
235-
'dimmer2' : 'ShellyDimmer2',
236-
'rgbw2' : 'ShellyRGBW2',
237228
}
238229
return options.get(type, type)
239230

@@ -341,7 +332,7 @@ def flash_firmware(self):
341332
dlurl = self.dlurl.replace('https', 'http')
342333
logger.debug(f"curl -qsS http://{self.wifi_ip}/ota?url={dlurl}")
343334
response = requests.get(f'http://{self.wifi_ip}/ota?url={dlurl}')
344-
logger.debug(response.text)
335+
logger.trace(response.text)
345336

346337

347338
def parse_version(vs):
@@ -385,12 +376,12 @@ def write_hap_setup_code(wifi_ip, hap_setup_code):
385376
value={'code': hap_setup_code}
386377
logger.debug(f"requests.post(url='http://{wifi_ip}/rpc/HAP.Setup', json={value}")
387378
response = requests.post(url=f'http://{wifi_ip}/rpc/HAP.Setup', json={'code': hap_setup_code})
388-
logger.debug(response.text)
379+
logger.trace(response.text)
389380
if response.text.startswith('null'):
390381
logger.info(f"Done.")
391382

392383
def write_flash(device_info, hap_setup_code):
393-
logger.debug(f"\n{WHITE}write_flash{NC}")
384+
logger.debug(f"{PURPLE}[Write Flash]{NC}")
394385
flashed = False
395386
device_info.flash_firmware()
396387
logger.info(f"waiting for {device_info.friendly_host} to reboot...")
@@ -408,7 +399,9 @@ def write_flash(device_info, hap_setup_code):
408399
break
409400
time.sleep(2)
410401
if onlinecheck == device_info.flash_fw_version:
411-
logger.info(f"{GREEN}Successfully flashed {device_info.friendly_host} to {device_info.flash_fw_version}{NC}")
402+
global flashed_devices
403+
flashed_devices +=1
404+
logger.critical(f"{GREEN}Successfully flashed {device_info.friendly_host} to {device_info.flash_fw_version}{NC}")
412405
if hap_setup_code:
413406
write_hap_setup_code(device_info.wifi_ip, hap_setup_code)
414407
else:
@@ -428,8 +421,8 @@ def write_flash(device_info, hap_setup_code):
428421
logger.debug("Current: %s" % onlinecheck)
429422

430423
def parse_info(device_info, action, dry_run, quiet_run, silent_run, mode, exclude, hap_setup_code, requires_upgrade):
431-
logger.info(f"")
432-
logger.debug(f"{WHITE}parse_info{NC}")
424+
logger.debug(f"")
425+
logger.debug(f"{PURPLE}[Parse Info]{NC}")
433426
logger.trace(f"device_info: {device_info}")
434427

435428
perform_flash = False
@@ -455,14 +448,16 @@ def parse_info(device_info, action, dry_run, quiet_run, silent_run, mode, exclud
455448
logger.debug(f"host: {host}")
456449
logger.debug(f"device_name: {device_name}")
457450
logger.debug(f"device_id: {device_id}")
451+
logger.debug(f"wifi_ip: {wifi_ip}")
458452
logger.debug(f"model: {model}")
459453
logger.debug(f"stock_model: {stock_model}")
460454
logger.debug(f"colour_mode: {colour_mode}")
455+
logger.debug(f"sys_temp: {sys_temp}")
461456
logger.debug(f"action: {action}")
462457
logger.debug(f"flash mode: {mode}")
463458
logger.debug(f"requires_upgrade: {requires_upgrade}")
464-
logger.debug(f"current_fw_version: {current_fw_version}")
465-
logger.debug(f"flash_fw_version: {flash_fw_version}")
459+
logger.debug(f"current_fw_version: {current_fw_type_str} {current_fw_version}")
460+
logger.debug(f"flash_fw_version: {flash_fw_type_str} {flash_fw_version}")
466461
logger.debug(f"force_version: {force_version}")
467462
logger.debug(f"dlurl: {dlurl}")
468463

@@ -486,6 +481,7 @@ def parse_info(device_info, action, dry_run, quiet_run, silent_run, mode, exclud
486481
latest_fw_label = flash_fw_version
487482

488483
if (not quiet_run or (quiet_run and (is_newer(flash_fw_version, current_fw_version) or force_version and dlurl and parse_version(flash_fw_version) != parse_version(current_fw_version)))) and requires_upgrade != 'Done':
484+
logger.info(f"")
489485
logger.info(f"{WHITE}Host: {NC}http://{host}")
490486
logger.info(f"{WHITE}Device Name: {NC}{device_name}")
491487
logger.info(f"{WHITE}Device ID: {NC}{device_id}")
@@ -543,7 +539,7 @@ def parse_info(device_info, action, dry_run, quiet_run, silent_run, mode, exclud
543539
logger.info("Does not need flashing...")
544540
return 0
545541

546-
logger.debug(f"\nperform_flash: {perform_flash}\n")
542+
logger.debug(f"perform_flash: {perform_flash}")
547543
if perform_flash == True and dry_run == False and silent_run == False:
548544
if requires_upgrade == True:
549545
flash_message = f"{message} {keyword}"
@@ -564,9 +560,10 @@ def parse_info(device_info, action, dry_run, quiet_run, silent_run, mode, exclud
564560
write_flash(device_info, hap_setup_code)
565561

566562
def probe_device(device, action, dry_run, quiet_run, silent_run, mode, exclude, version, variant, hap_setup_code):
567-
logger.debug(f"\n{WHITE}probe_device{NC}")
563+
logger.debug("")
564+
logger.debug(f"{PURPLE}[Probe Device]{NC}")
568565
d_info = json.dumps(device, indent = 4)
569-
logger.trace(f"Device Info: {d_info}")
566+
logger.trace(f"device_info: {d_info}")
570567

571568
requires_upgrade = False
572569
if mode == 'keep':
@@ -591,9 +588,9 @@ def probe_device(device, action, dry_run, quiet_run, silent_run, mode, exclude,
591588
elif flashmode == 'stock':
592589
deviceinfo.update_to_stock(stock_release_info)
593590
if deviceinfo.fw_type == "homekit" and float(f"{parse_version(deviceinfo.info['version'])[0]}.{parse_version(deviceinfo.info['version'])[1]}") < 2.1:
594-
logger.info(f"{WHITE}Host: {NC}{deviceinfo.host}")
595-
logger.info(f"Version {deviceinfo.info['version']} is to old for this script,")
596-
logger.info(f"please update via the device webUI.\n")
591+
logger.error(f"{WHITE}Host: {NC}{deviceinfo.host}")
592+
logger.error(f"Version {deviceinfo.info['version']} is to old for this script,")
593+
logger.error(f"please update via the device webUI.\n")
597594
else:
598595
parse_info(deviceinfo, action, dry_run, quiet_run, silent_run, flashmode, exclude, hap_setup_code, requires_upgrade)
599596
if requires_upgrade:
@@ -607,13 +604,15 @@ def probe_device(device, action, dry_run, quiet_run, silent_run, mode, exclude,
607604
def device_scan(hosts, action, dry_run, quiet_run, silent_run, mode, exclude, version, variant, hap_setup_code):
608605
if hosts:
609606
for host in hosts:
610-
logger.debug(f"\n{WHITE}device_scan{NC}")
607+
logger.debug(f"")
608+
logger.debug(f"{PURPLE}[Device Scan] manual{NC}")
611609
deviceinfo = Device(host)
612610
deviceinfo.get_device_info()
613611
if deviceinfo.fw_type is not None:
614612
device = {'host': deviceinfo.host, 'wifi_ip': deviceinfo.wifi_ip, 'fw_type': deviceinfo.fw_type, 'device_url': deviceinfo.device_url, 'info': deviceinfo.info}
615613
probe_device(device, action, dry_run, quiet_run, silent_run, mode, exclude, version, variant, hap_setup_code)
616614
else:
615+
logger.debug(f"{PURPLE}[Device Scan] automatic scan{NC}")
617616
logger.info(f"{WHITE}Scanning for Shelly devices...{NC}")
618617
zc = zeroconf.Zeroconf()
619618
listener = MyListener()
@@ -623,10 +622,14 @@ def device_scan(hosts, action, dry_run, quiet_run, silent_run, mode, exclude, ve
623622
try:
624623
deviceinfo = listener.queue.get(timeout=20)
625624
except queue.Empty:
626-
logger.info(f"\n{GREEN}Devices found: {total_devices} Upgradeable: {upgradeable_devices}{NC}")
625+
logger.info(f"")
626+
logger.info(f"{GREEN}Devices found: {total_devices} Upgradeable: {upgradeable_devices} Flashed: {flashed_devices}{NC}")
627+
if args.log_filename:
628+
logger.info(f"Log file created: {args.log_filename}")
627629
zc.close()
628630
break
629-
logger.debug(f"\n{WHITE}device_scan{NC}")
631+
logger.debug(f"")
632+
logger.debug(f"{PURPLE}[Device Scan] action queue entry{NC}")
630633
deviceinfo.get_device_info()
631634
if deviceinfo.fw_type is not None:
632635
device = {'host': deviceinfo.host, 'wifi_ip': deviceinfo.wifi_ip, 'fw_type': deviceinfo.fw_type, 'device_url': deviceinfo.device_url, 'info' : deviceinfo.info}
@@ -644,24 +647,50 @@ def device_scan(hosts, action, dry_run, quiet_run, silent_run, mode, exclude, ve
644647
parser.add_argument('-y', '--assume-yes', action="store_true", dest='silent_run', default=False, help="Do not ask any confirmation to perform the flash.")
645648
parser.add_argument('-V', '--version',type=str, action="store", dest="version", default=False, help="Force a particular version.")
646649
parser.add_argument('-c', '--hap-setup-code', action="store", dest="hap_setup_code", default=False, help="Configure HomeKit setup code, after flashing.")
650+
parser.add_argument('-v', '--verbose', action="store", dest="verbose", choices=['0', '1', '2', '3', '4', '5'], default='3', help="Enable verbose logging 0=critical, 1=error, 2=warning, 3=info, 4=debug, 5=trace.")
647651
parser.add_argument('--variant', action="store", dest="variant", default=False, help="Prerelease variant name.")
648-
parser.add_argument('-v', '--verbose', action="store", dest="verbose", choices=['0', '1'], help="Enable verbose logging level.")
652+
parser.add_argument('--log-file', action="store", dest="log_filename", default=False, help="Create output log file with chosen filename.")
649653
parser.add_argument('hosts', type=str, nargs='*')
650654
args = parser.parse_args()
651655
action = 'list' if args.list else 'flash'
652656
args.mode = 'stock' if args.mode == 'revert' else args.mode
653657
args.hap_setup_code = f"{args.hap_setup_code[:3]}-{args.hap_setup_code[3:-3]}-{args.hap_setup_code[5:]}" if args.hap_setup_code and '-' not in args.hap_setup_code else args.hap_setup_code
654-
if args.verbose and '0' in args.verbose:
655-
logger.setLevel(logging.DEBUG)
656-
elif args.verbose and '1' in args.verbose:
657-
logger.setLevel(logging.TRACE)
658+
659+
sh = logging.StreamHandler()
660+
sh.setFormatter(logging.Formatter('%(message)s'))
661+
sh.setLevel(log_level[args.verbose])
662+
if args.log_filename:
663+
fh = logging.FileHandler(args.log_filename, mode='w', encoding='utf-8')
664+
fh.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(lineno)d %(message)s'))
665+
fh.setLevel(log_level[args.verbose])
666+
logger.addHandler(fh)
667+
logger.addHandler(sh)
668+
669+
# Windows and log file do not support acsii colours
670+
if not args.log_filename and not arch.startswith('Win'):
671+
WHITE = '\033[1m'
672+
RED = '\033[1;91m'
673+
GREEN = '\033[1;92m'
674+
YELLOW = '\033[1;93m'
675+
BLUE = '\033[1;94m'
676+
PURPLE = '\033[1;95m'
677+
NC = '\033[0m'
678+
else:
679+
WHITE = ''
680+
RED = ''
681+
GREEN = ''
682+
YELLOW = ''
683+
BLUE = ''
684+
PURPLE = ''
685+
NC = ''
686+
658687

659688
homekit_release_info = None
660689
stock_release_info = None
661690
app_version = "2.1.0"
662691

663-
logger.debug(f"{WHITE}app_version: {app_version}{NC}")
664-
logger.debug(f"{PURPLE}OS: {arch}{NC}")
692+
logger.debug(f"OS: {PURPLE}{arch}{NC}")
693+
logger.debug(f"app_version: {app_version}")
665694
logger.debug(f"manual_hosts: {args.hosts}")
666695
logger.debug(f"action: {action}")
667696
logger.debug(f"mode: {args.mode}")
@@ -674,6 +703,7 @@ def device_scan(hosts, action, dry_run, quiet_run, silent_run, mode, exclude, ve
674703
logger.debug(f"exclude: {args.exclude}")
675704
logger.debug(f"variant: {args.variant}")
676705
logger.debug(f"verbose: {args.verbose}")
706+
logger.debug(f"log_filename: {args.log_filename}")
677707

678708
if not args.hosts and not args.do_all:
679709
logger.info(f"{WHITE}Requires a hostname or -a | --all{NC}")
@@ -690,23 +720,24 @@ def device_scan(hosts, action, dry_run, quiet_run, silent_run, mode, exclude, ve
690720

691721
try:
692722
fp = requests.get("https://api.shelly.cloud/files/firmware", timeout=3)
723+
logger.debug(f"stock_release_info status code: {fp.status_code}")
693724
if fp.status_code == 200:
694725
stock_release_info = json.loads(fp.content)
695726
except requests.exceptions.RequestException as err:
696-
logger.debug(fp.status_code)
727+
logger.critical(f"{RED}CRITICAL:{NC} {err}")
728+
logger.trace(f"stock_release_info: {json.dumps(stock_release_info, indent = 4)}")
697729
try:
698730
fp = requests.get("https://rojer.me/files/shelly/update.json", timeout=3)
731+
logger.debug(f"homekit_release_info status code: {fp.status_code}")
699732
if fp.status_code == 200:
700733
homekit_release_info = json.loads(fp.content)
701734
except requests.exceptions.RequestException as err:
702-
logger.debug(err)
703-
704-
logger.trace(f"\n{WHITE}stock_release_info:{NC}{stock_release_info}")
705-
logger.trace(f"\n{WHITE}homekit_release_info:{NC}{homekit_release_info}")
735+
logger.critical(f"{RED}CRITICAL:{NC} {err}")
736+
logger.trace(f"homekit_release_info: {json.dumps(homekit_release_info, indent = 4)}")
706737

707738
if not stock_release_info or not homekit_release_info:
708-
logger.warning(f"{RED}Failed to lookup online version information{NC}")
709-
logger.warning("For more information please point your web browser to:")
710-
logger.warning("https://github.com/mongoose-os-apps/shelly-homekit/wiki/Flashing#script-fails-to-run")
739+
logger.error(f"{RED}Failed to lookup online version information{NC}")
740+
logger.error("For more information please point your web browser to:")
741+
logger.error("https://github.com/mongoose-os-apps/shelly-homekit/wiki/Flashing#script-fails-to-run")
711742
else:
712743
device_scan(args.hosts, action, args.dry_run, args.quiet_run, args.silent_run, args.mode, args.exclude, args.version, args.variant, args.hap_setup_code)

0 commit comments

Comments
 (0)