Browse Source

start of pico ota implementation

Thomas Buck 1 year ago
parent
commit
c20811eace
2 changed files with 168 additions and 0 deletions
  1. 1
    0
      .gitignore
  2. 167
    0
      pico_ota.py

+ 1
- 0
.gitignore View File

@@ -1 +1,2 @@
1 1
 __pycache__
2
+tmp

+ 167
- 0
pico_ota.py View File

@@ -0,0 +1,167 @@
1
+#!/usr/bin/env python3
2
+
3
+# Uses the Gitea API to fetch the latest revision of the project from a repo.
4
+#
5
+# Inspired by:
6
+# https://github.com/olivergregorius/micropython_ota
7
+#
8
+# ----------------------------------------------------------------------------
9
+# "THE BEER-WARE LICENSE" (Revision 42):
10
+# <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
11
+# you can do whatever you want with this stuff. If we meet some day, and you
12
+# think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
13
+# ----------------------------------------------------------------------------
14
+
15
+import util
16
+import sys
17
+import os
18
+
19
+# to check if we're actually running on MicroPython
20
+on_pico = False
21
+try:
22
+    import uos
23
+    on_pico = True
24
+except Exception as e:
25
+    print()
26
+    if hasattr(sys, "print_exception"):
27
+        sys.print_exception(e)
28
+    else:
29
+        print(e)
30
+    print()
31
+
32
+class PicoOTA:
33
+    def __init__(self, host, repo, branch = None):
34
+        self.host = host
35
+        self.repo = repo
36
+        self.branch = branch
37
+
38
+        self.get = None
39
+        self.update_path = "."
40
+        self.blacklist = []
41
+
42
+    def path(self, p):
43
+        self.update_path = p
44
+
45
+    def ignore(self, path):
46
+        if not path in self.blacklist:
47
+            self.blacklist.append(path)
48
+
49
+    def fetch(self, url):
50
+        # lazily initialize WiFi
51
+        if self.get == None:
52
+            self.get = util.getRequests()
53
+            if self.get == None:
54
+                return None
55
+
56
+        try:
57
+            #print("GET " + url)
58
+            r = self.get(url)
59
+            r.close()
60
+            return r
61
+        except Exception as e:
62
+            print()
63
+            if hasattr(sys, "print_exception"):
64
+                sys.print_exception(e)
65
+            else:
66
+                print(e)
67
+            print()
68
+            return None
69
+
70
+    def check(self, verbose = False):
71
+        if self.branch == None:
72
+            # get default branch
73
+            r = self.fetch(self.host + "/api/v1/repos/" + self.repo).json()
74
+            self.branch = r["default_branch"]
75
+
76
+            if verbose:
77
+                print("Selected default branch " + self.branch)
78
+
79
+        # check for latest commit in branch
80
+        r = self.fetch(self.host + "/api/v1/repos/" + self.repo + "/branches/" + self.branch).json()
81
+        commit = r["commit"]["id"]
82
+
83
+        if verbose:
84
+            print("Latest commit is " + commit)
85
+
86
+        current = ""
87
+        try:
88
+            f = open(os.path.join(self.update_path, "ota_version"), "r")
89
+            current = f.readline().strip()
90
+            f.close()
91
+        except Exception as e:
92
+            print()
93
+            if hasattr(sys, "print_exception"):
94
+                sys.print_exception(e)
95
+            else:
96
+                print(e)
97
+            print()
98
+
99
+        if verbose:
100
+            if current != commit:
101
+                print("Current commit " + current + " is different!")
102
+            else:
103
+                print("No update required")
104
+
105
+        return (current != commit, commit)
106
+
107
+    def update_to_commit(self, commit, verbose = False):
108
+        # list all files for a commit
109
+        r = self.fetch(self.host + "/api/v1/repos/" + self.repo + "/git/trees/" + commit).json()
110
+
111
+        # TODO does not support sub-folders
112
+
113
+        if verbose:
114
+            if len(r["tree"]) > 0:
115
+                print(str(len(r["tree"])) + " files in repo:")
116
+                for f in r["tree"]:
117
+                    if f["path"] in self.blacklist:
118
+                        print("  - (IGNORED) " + f["path"])
119
+                    else:
120
+                        print("  - " + f["path"])
121
+            else:
122
+                print("No files in repo?!")
123
+
124
+        for f in r["tree"]:
125
+            if f["path"] in self.blacklist:
126
+                continue
127
+
128
+            # get a file from a commit
129
+            r = self.fetch(self.host + "/" + self.repo + "/raw/commit/" + commit + "/" + f["path"]).text
130
+
131
+            if verbose:
132
+                print("Writing " + f["path"] + " to " + self.update_path)
133
+
134
+            # overwrite existing file
135
+            f = open(os.path.join(self.update_path, f["path"]), "w")
136
+            f.write(r)
137
+            f.close()
138
+
139
+        # Write new commit id to local file
140
+        f = open(os.path.join(self.update_path, "ota_version"), "w")
141
+        f.write(commit + os.linesep)
142
+        f.close()
143
+
144
+if __name__ == "__main__":
145
+    ota = PicoOTA("https://git.xythobuz.de", "thomas/rgb-matrix-visualizer")
146
+
147
+    # stuff not needed on Pico
148
+    ota.ignore(".gitignore")
149
+    ota.ignore("README.md")
150
+    ota.ignore("copy.sh")
151
+    ota.ignore("config.py")
152
+    ota.ignore("fonts")
153
+    ota.ignore("images")
154
+    ota.ignore("bdf.py")
155
+    ota.ignore("camp_small.py")
156
+    ota.ignore("gamepad.py")
157
+    ota.ignore("pi.py")
158
+    ota.ignore("test.py")
159
+
160
+    if not on_pico:
161
+        if not os.path.exists("tmp"):
162
+            os.makedirs("tmp")
163
+        ota.path("tmp")
164
+
165
+    newer, commit = ota.check(True)
166
+    if newer:
167
+        ota.update_to_commit(commit, True)

Loading…
Cancel
Save