Skip to content

Commit ce77dfa

Browse files
authored
Merge pull request #74 from reloxx13/feature/generate_binary
Feature/generate binary for Windows
2 parents 344bfdd + 2469eff commit ce77dfa

File tree

8 files changed

+75
-6
lines changed

8 files changed

+75
-6
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@
22
*.log
33
*.pyc
44
*.pyo
5+
.idea
56

7+
/Release/build/*
8+
/Release/dist/*
9+
10+
11+
!empty

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The included final Arduino Sketch binary is v5.9.1, defaulting `WIFI_CONFIG_TOOL
1515
### Prerequisites
1616

1717
**Windows users:**
18+
Skip if you use the sonota.exe file
1819
* Download and install Python v3.5.x: https://www.python.org/downloads/windows/
1920
(Python v3.5.x is recommended for Windows as the `netifaces` module has prebuilt wheels)
2021
* **All firewalls must be disabled** when running SonOTA
@@ -32,11 +33,20 @@ The included final Arduino Sketch binary is v5.9.1, defaulting `WIFI_CONFIG_TOOL
3233

3334
### Running
3435

36+
Method 1)
3537
After setting up the prerequisites, download the repo (either using `git clone`, or downloading and extracting the .zip file). Then install the Python dependencies by changing into the SonOTA directory and running:
3638
`pip3 install --user -r requirements.txt`
3739

3840
Once installed, you can run SonOTA (`./sonota.py`, you may need something like `python3 sonota.py` on Windows), and it will prompt you for the various settings it needs, and guide you through what to do for each step.
3941

42+
Method 2)
43+
Download latest sonota.exe from the releases page
44+
45+
Run the exe as administrator**
46+
47+
A Console Windows will popup and it will prompt you for the various settings it needs, and guide you through what to do for each step.
48+
49+
4050
**Ensure all firewalls are disabled on all WiFi networks, including FinalStage when connected.** This is the most common reason things to not complete.
4151

4252
Once complete and Sonoff-Tasmota is installed, you will have an AP called `sonoff-####` (note: this will be up for a minute then down for a minute until configured).
@@ -85,6 +95,11 @@ This program is based on research documented here:
8595

8696
The script is fairly well documented (I think) - apart from that above stated links should provide some context of what's been done how and why. Feel free to open issue tickets or contact me directly: [email protected]
8797

98+
99+
100+
### Building own Exe File
101+
just run the built.bat in the Release folder to create your own sonota.exe. You will find the exe in the Release/dist folder.
102+
88103
# Compatibility
89104

90105
Please see the [wiki](https://github.com/mirko/SonOTA/wiki) for known working configurations.

Release/build.bat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pyinstaller sonota.spec --clean
2+
pause

Release/build/empty

Whitespace-only changes.

Release/dist/empty

Whitespace-only changes.

Release/sonota.spec

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# -*- mode: python -*-
2+
3+
block_cipher = None
4+
5+
added_files = [
6+
('..\static','static'),
7+
('..\ssl','ssl')
8+
]
9+
10+
a = Analysis(['..\\sonota.py'],
11+
pathex=[],
12+
binaries=[],
13+
datas = added_files,
14+
hiddenimports=[],
15+
hookspath=[],
16+
runtime_hooks=[],
17+
excludes=[],
18+
win_no_prefer_redirects=False,
19+
win_private_assemblies=False,
20+
cipher=block_cipher)
21+
pyz = PYZ(a.pure, a.zipped_data,
22+
cipher=block_cipher)
23+
exe = EXE(pyz,
24+
a.scripts,
25+
a.binaries,
26+
a.zipfiles,
27+
a.datas,
28+
name='sonota',
29+
debug=True,
30+
strip=False,
31+
upx=True,
32+
console=True,
33+
uac_admin=False,
34+
icon='..\\res\\wifi.ico' )
35+

res/wifi.ico

175 KB
Binary file not shown.

sonota.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,8 @@ def on_message(self, message):
343343

344344
if self.setup_completed and self.test and not self.upgrade:
345345

346-
hash_user1 = self.getFirmwareHash("static/%s" % upgrade_file_user1)
347-
hash_user2 = self.getFirmwareHash("static/%s" % upgrade_file_user2)
346+
hash_user1 = self.getFirmwareHash(resource_path(os.path.join("static", upgrade_file_user1)))
347+
hash_user2 = self.getFirmwareHash(resource_path(os.path.join("static", upgrade_file_user2)))
348348

349349
if not args.serving_host:
350350
raise ValueError('args.serving_host is required')
@@ -408,7 +408,7 @@ def getFirmwareHash(self, filePath):
408408
with open(filePath, "rb") as firmware:
409409
hash_user = sha256(firmware.read()).hexdigest()
410410
except IOError as e:
411-
log.warn(e)
411+
log.warning(e)
412412
return hash_user
413413

414414

@@ -419,7 +419,7 @@ def make_app():
419419
# handling actual payload communication on WebSockets
420420
(r'/api/ws', WebSocketHandler),
421421
(r'/slowota/(.*)', SlowOTAUpdate),
422-
(r'/ota/(.*)', OTAUpdate, {'path': "static/"}),
422+
(r'/ota/(.*)', OTAUpdate, {'path': resource_path("static/")}),
423423
]
424424
return tornado.web.Application(apps)
425425

@@ -474,10 +474,21 @@ def promptforval(msg):
474474
if val:
475475
return val
476476

477+
def resource_path(relative_path):
478+
""" Get absolute path to resource, works for dev and for PyInstaller """
479+
try:
480+
# PyInstaller creates a temp folder and stores path in _MEIPASS
481+
base_path = sys._MEIPASS
482+
except Exception:
483+
base_path = os.path.dirname(sys.argv[0])
484+
485+
return os.path.join(base_path, relative_path)
486+
477487
def checkargs():
478488
# Make sure all of the binary files that are needed are there
479489
for fn in [arduino_file, upgrade_file_user1, upgrade_file_user2]:
480490
fn = os.path.join('static', fn)
491+
fn = resource_path(fn)
481492
if not os.path.isfile(fn):
482493
log.critical("Required file missing!", fn)
483494
sys.exit(1)
@@ -642,8 +653,8 @@ def stage2():
642653
app.listen(DEFAULT_PORT_HTTP)
643654

644655
app_ssl = tornado.httpserver.HTTPServer(app, ssl_options={
645-
"certfile": "ssl/server.crt",
646-
"keyfile": "ssl/server.key",
656+
"certfile": resource_path("ssl/server.crt"),
657+
"keyfile": resource_path("ssl/server.key"),
647658
})
648659
# listening on HTTPS port to catch initial POST request to eu-disp.coolkit.cc
649660
app_ssl.listen(DEFAULT_PORT_HTTPS)

0 commit comments

Comments
 (0)