Skip to content

Commit 938f485

Browse files
Merge remote-tracking branch 'mrg_main/main' into work
2 parents 5d3cf01 + d6b792c commit 938f485

File tree

122 files changed

+12055
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+12055
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 Tasmota
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[![Tasmota install](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
2+
3+
![Tasmota logo](https://github.com/arendst/Tasmota/blob/development/tools/logo/TASMOTA_FullLogo_Vector.svg#gh-light-mode-only)![Tasmota logo](https://github.com/arendst/Tasmota/blob/development/tools/logo/TASMOTA_FullLogo_Vector_White.svg#gh-dark-mode-only)
4+
5+
Alternative firmware for ESP8266/ESP32 based devices with **easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX**.
6+
7+
If you like **Tasmota**, give it a star, or fork it and contribute!
8+
9+
[![GitHub stars](https://img.shields.io/github/stars/arendst/Tasmota.svg?style=social&label=Star)](https://github.com/arendst/Tasmota/stargazers)
10+
[![GitHub forks](https://img.shields.io/github/forks/arendst/Tasmota.svg?style=social&label=Fork)](https://github.com/arendst/Tasmota/network)
11+
[![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota)
12+
13+
See [CHANGELOG](https://github.com/arendst/Tasmota/blob/development/CHANGELOG.md) for changes since last release.
14+
15+
Easy initial installation of Tasmota via **[Tasmota WebInstaller](https://tasmota.github.io/install/)**. The actual development / release builds and the unofficial firmwares are available. It is important to note that development binaries are based on the current codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted.
16+
The unofficial special build variants are **not** tested nor supported. Dont blame anyone when using ;-)
17+
18+
## Disclaimer
19+
20+
:warning: **DANGER OF ELECTROCUTION** :warning:
21+
22+
If your device connects to mains electricity (AC power) there is danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician (***Beware:*** certain countries prohibit installation without a licensed electrician present). Remember: _**SAFETY FIRST**_. It is not worth the risk to yourself, your family and your home if you don't know exactly what you are doing. Never tinker or try to flash a device using the serial programming interface while it is connected to MAINS ELECTRICITY (AC power).
23+
24+
We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site.

favicon.ico

15 KB
Binary file not shown.

genManifest.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/usr/bin/python3
2+
3+
from platform import release
4+
import sys
5+
import os
6+
from os import listdir
7+
from os import mkdir
8+
from os import remove
9+
from os import path
10+
import json
11+
import requests
12+
import gzip
13+
import re
14+
15+
16+
def filter_builds(data):
17+
"""
18+
Removes non-existing MCU firmware variant from manifest, indicated by 'size' entry is None.
19+
"""
20+
filtered_builds = []
21+
for build in data['builds']:
22+
if all(part['size'] is not None for part in build['parts']):
23+
filtered_builds.append(build)
24+
data['builds'] = filtered_builds
25+
return data
26+
27+
def convertJSON(infile, outfile):
28+
with open(infile) as json_file:
29+
data = json.load(json_file)
30+
for build in data['builds']:
31+
for part in build['parts']:
32+
part['path'] = part['path'].replace("..", "https://tasmota.github.io/install")
33+
# Add firmware size
34+
firmware_path = part['path'].replace("https://tasmota.github.io/install", ".").replace(".factory", "")
35+
if os.path.exists(firmware_path):
36+
part['size'] = os.path.getsize(firmware_path)
37+
else:
38+
part['size'] = None # If the file doesn't exist, set size to None
39+
40+
filter_builds(data)
41+
j = json.dumps(data, indent=4)
42+
# Write updated data to JSON
43+
with open(outfile, "w") as f:
44+
f.write(j)
45+
46+
def getManifestEntry(manifest):
47+
entry = {}
48+
with open(manifest) as json_file:
49+
data = json.load(json_file)
50+
entry['path'] = "https://tasmota.github.io/install/" + manifest
51+
entry['name'] = data['name']
52+
entry['chipFamilies'] = []
53+
for build in data['builds']:
54+
entry['chipFamilies'].append(build['chipFamily'])
55+
return entry
56+
57+
58+
59+
def main(args):
60+
path_manifests = path.join('manifest')
61+
path_manifests_ext = path.join('manifest_ext')
62+
if not path.exists(path_manifests):
63+
print("No manifest folder, exiting ...")
64+
return -1
65+
files = listdir(path_manifests)
66+
if len(files) == 0:
67+
print("Empty manifest folder, exiting ...")
68+
return -1
69+
if path.exists(path_manifests_ext):
70+
m_e_files = listdir(path_manifests_ext)
71+
# for file in m_e_files:
72+
# remove(file)
73+
else:
74+
mkdir(path_manifests_ext)
75+
76+
77+
output = {}
78+
79+
for file in files:
80+
# create absolute path-version of each manifest file in /manifest_ext
81+
convertJSON(path.join(path_manifests,file),path.join(path_manifests_ext,file))
82+
line = file.split('.')
83+
if len(line) != 4:
84+
print("Incompatible path name, ignoring file:",file)
85+
continue
86+
# print(line[1])
87+
if line[0] not in output:
88+
output[line[0]] = [[],[],[],[],[],[]]
89+
if line[1] == "tasmota":
90+
output[line[0]][0].insert(0,getManifestEntry(path.join(path_manifests_ext,file))) # vanilla first
91+
continue
92+
elif line[1] == "tasmota32":
93+
output[line[0]][1].insert(0,getManifestEntry(path.join(path_manifests_ext,file)))
94+
continue
95+
elif len(line[1].split('-')) == 1: #solo1,4M,...
96+
output[line[0]][2].append(getManifestEntry(path.join(path_manifests_ext,file)))
97+
continue
98+
name_components = line[1].split('-')
99+
if name_components[0] == "tasmota":
100+
if len(name_components[1]) == 2 and name_components[1].isupper():
101+
output[line[0]][1].append(getManifestEntry(path.join(path_manifests_ext,file))) # language versions last
102+
continue
103+
output[line[0]][0].append(getManifestEntry(path.join(path_manifests_ext,file)))
104+
continue
105+
elif name_components[0] == "tasmota32":
106+
if len(name_components[1]) == 2 and name_components[1].isupper():
107+
output[line[0]][3].append(getManifestEntry(path.join(path_manifests_ext,file))) # language versions last
108+
continue
109+
output[line[0]][2].append(getManifestEntry(path.join(path_manifests_ext,file)))
110+
continue
111+
else: #solo1,4M,...
112+
if len(name_components[1]) == 2 and name_components[1].isupper():
113+
output[line[0]][5].append(getManifestEntry(path.join(path_manifests_ext,file))) # language versions last
114+
continue
115+
output[line[0]][4].append(getManifestEntry(path.join(path_manifests_ext,file)))
116+
# print(output)
117+
118+
for section in output:
119+
merged = sorted(output[section][0],key=lambda d: d['name']) + sorted(output[section][1],key=lambda d: d['name']) + sorted(output[section][2],key=lambda d: d['name']) + sorted(output[section][3],key=lambda d: d['name']) + sorted(output[section][4],key=lambda d: d['name']) + sorted(output[section][5],key=lambda d: d['name'])
120+
output[section] = merged
121+
122+
release = output.pop("release")
123+
development = output.pop("development")
124+
unofficial = output.pop("unofficial")
125+
126+
127+
final_json = {}
128+
final_json["release"] = release
129+
final_json["development"] = development
130+
final_json["unofficial"] = unofficial
131+
for key in output:
132+
final_json[key] = output[key] # just in case we have another section in the future
133+
134+
135+
# print(final_json)
136+
137+
j = json.dumps(final_json,indent=4)
138+
f = open("manifests.json", "w")
139+
f.write(j)
140+
f.close()
141+
142+
# intermediate version with double output (DEPRECATED)
143+
f = open("manifests_new.json", "w")
144+
f.write(j)
145+
f.close()
146+
# end deprecated version
147+
148+
if __name__ == '__main__':
149+
sys.exit(main(sys.argv))
150+
# end if

genManifestRelease.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/python3
2+
3+
from curses.ascii import isupper
4+
from platform import release
5+
import sys
6+
import os
7+
from os import listdir
8+
from os import mkdir
9+
from os import remove
10+
from os import path
11+
import json
12+
13+
def filter_builds(data):
14+
"""
15+
Removes non-existing MCU firmware variant from manifest, indicated by 'size' entry is None.
16+
"""
17+
filtered_builds = []
18+
for build in data['builds']:
19+
if all(part['size'] is not None for part in build['parts']):
20+
filtered_builds.append(build)
21+
data['builds'] = filtered_builds
22+
return data
23+
24+
def convertJSON(infile, outfile, tag):
25+
with open(infile) as json_file:
26+
data = json.load(json_file)
27+
for build in data['builds']:
28+
for part in build['parts']:
29+
components = part['path'].split("/")
30+
firmware_path = part['path']
31+
part['path'] = "https://github.com/tasmota/install/releases/download/" + tag + "/" + components[-1]
32+
# Add firmware size with ugly path fix for firmware path
33+
firmware_path = firmware_path.replace(".factory", "").replace("../", "./").replace("//", "/")
34+
if os.path.exists(firmware_path):
35+
part['size'] = os.path.getsize(firmware_path)
36+
else:
37+
part['size'] = None # If the file doesn't exist, set size to None
38+
39+
filter_builds(data)
40+
j = json.dumps(data, indent=4)
41+
# Write updated data to JSON
42+
with open(outfile, "w") as f:
43+
f.write(j)
44+
45+
def getManifestEntry(manifest, tag):
46+
entry = {}
47+
with open(manifest) as json_file:
48+
data = json.load(json_file)
49+
components = manifest.split("/")
50+
entry['path'] = "https://github.com/tasmota/install/releases/download/" + tag + "/" + components[-1]
51+
entry['name'] = data['name']
52+
entry['chipFamilies'] = []
53+
for build in data['builds']:
54+
entry['chipFamilies'].append(build['chipFamily'])
55+
return entry
56+
57+
def getTag():
58+
with open("tag_latest.txt") as tag:
59+
tag_latest = tag.readline().strip()
60+
return tag_latest
61+
62+
63+
def main(args):
64+
path_manifests = path.join('manifest')
65+
path_manifests_release = path.join('manifest_release')
66+
if not path.exists(path_manifests):
67+
print("No manifest folder, exiting ...")
68+
return -1
69+
files = listdir(path_manifests)
70+
if len(files) == 0:
71+
print("Empty manifest folder, exiting ...")
72+
return -1
73+
if path.exists(path_manifests_release):
74+
m_e_files = listdir(path_manifests_release)
75+
# for file in m_e_files:
76+
# remove(file)
77+
else:
78+
mkdir(path_manifests_release)
79+
80+
tag_latest = getTag()
81+
82+
output = {}
83+
84+
for file in files:
85+
# create absolute path-version of each manifest file in /manifest_ext
86+
convertJSON(path.join(path_manifests,file),path.join(path_manifests_release,file),tag_latest)
87+
line = file.split('.')
88+
if len(line) != 4:
89+
print("Incompatible path name, ignoring file:",file)
90+
continue
91+
# print(line[1])
92+
if line[0] not in output:
93+
output[line[0]] = [[],[],[],[],[],[]]
94+
if line[1] == "tasmota":
95+
print(path.join(path_manifests_release,file),tag_latest)
96+
output[line[0]][0].insert(0,getManifestEntry(path.join(path_manifests_release,file),tag_latest)) # vanilla first
97+
continue
98+
elif line[1] == "tasmota32":
99+
output[line[0]][1].insert(0,getManifestEntry(path.join(path_manifests_release,file),tag_latest))
100+
continue
101+
else: #solo1,4M,...
102+
output[line[0]][2].append(getManifestEntry(path.join(path_manifests_release,file),tag_latest))
103+
continue
104+
name_components = line[1].split('-')
105+
if name_components[0] == "tasmota":
106+
if len(name_components[1]) and name_components[1].isupper():
107+
output[line[0]][1].append(getManifestEntry(path.join(path_manifests_release,file),tag_latest)) # language versions last
108+
continue
109+
output[line[0]][0].append(getManifestEntry(path.join(path_manifests_release,file),tag_latest))
110+
continue
111+
elif name_components[0] == "tasmota32":
112+
if len(name_components[1]) and name_components[1].isupper():
113+
output[line[0]][3].append(getManifestEntry(path.join(path_manifests_release,file),tag_latest)) # language versions last
114+
continue
115+
output[line[0]][2].append(getManifestEntry(path.join(path_manifests_release,file),tag_latest))
116+
continue
117+
else: #solo1,4M,...
118+
if len(name_components[1]) and name_components[1].isupper():
119+
output[line[0]][5].append(getManifestEntry(path.join(path_manifests_release,file),tag_latest)) # language versions last
120+
continue
121+
output[line[0]][4].append(getManifestEntry(path.join(path_manifests_release,file),tag_latest))
122+
# print(output)
123+
124+
for section in output:
125+
merged = sorted(output[section][0],key=lambda d: d['name']) + sorted(output[section][1],key=lambda d: d['name']) + sorted(output[section][2],key=lambda d: d['name']) + sorted(output[section][3],key=lambda d: d['name']) + sorted(output[section][4],key=lambda d: d['name']) + sorted(output[section][5],key=lambda d: d['name'])
126+
output[section] = merged
127+
128+
release = output.pop("release")
129+
development = output.pop("development")
130+
unofficial = output.pop("unofficial")
131+
132+
133+
final_json = {}
134+
final_json["release"] = release
135+
final_json["development"] = development
136+
final_json["unofficial"] = unofficial
137+
for key in output:
138+
final_json[key] = output[key] # just in case we have another section in the future
139+
140+
#print(final_json)
141+
j = json.dumps(final_json,indent=4)
142+
f = open("manifests_release.json", "w")
143+
f.write(j)
144+
f.close()
145+
# end deprecated version
146+
147+
if __name__ == '__main__':
148+
sys.exit(main(sys.argv))
149+
# end if

0 commit comments

Comments
 (0)