I am trying to make the WebServer examples found in the Labs work.
I have a Pi-top[4] with the Robotics Kit. I have plugged in 4 LEDs.
I am using Visual Studio Code with the remorte SSH extension on my windows laptop to SSH tunnel into the Pi-top and modify and run the code on the Pi-top.
I want a WebController with 4 html buttons to turn on and off the LEDs on the Pi-Top.
I have been working through all of the examples in the SDK but I am stuck getting my HTML to correctly extend and modify the jinja blueprint templates.
I have this Python Code:
from pitop import Pitop
from pitop import LED, Button, UltrasonicSensor
from pitop.labs import RoverWebController
from time import sleep
from PIL import Image, ImageDraw
from datetime import datetime
import gevent
#setup Robot
print("Creating Robot Pitop")
myRobot = Pitop()
myRobot.add_component(Button("D6"), "Back Button")
myRobot.add_component(LED("D1"), "GreenLED")
myRobot.add_component(LED("D0"), "YellowLED")
myRobot.add_component(LED("D2"), "redRightLED")
myRobot.add_component(LED("D7"), "redLeftLED")
myRobot.add_component(UltrasonicSensor("D3"))
print("Created!")
print(type(myRobot.state))
for _ in myRobot.state:
print(_, myRobot.state[_])
#SETUP MiniSCREEN
ms = myRobot.miniscreen
#Setup MultiThreed Event handler
hub = gevent.get_hub()
#Setup Server
myServer = RoverWebController()
elapsed = 0.0
#Functions
def manageMiniScreen():
# global startTime
screenInvert =False
global elapsed
tick = 0.2
while True:
sleep(tick)
elapsed += tick
if ms.select_button.is_pressed:
if screenInvert == True:
screenInvert = False
else:
screenInvert = True
if ms.cancel_button.is_pressed:
print("Stopping Server")
print("X button on PiTop Pressed")
quit() #Close Python Script since ms.server_froever(), canot be stopped
makeScreen(elapsed, screenInvert)
def makeScreen(inputTime, invert=False):
if invert:
bgColor = "#000000"
penColor = "#FFFFFF"
else:
penColor = "#000000"
bgColor = "#FFFFFF"
thisScreen = Image.new(ms.mode, ms.size, bgColor)
thisCanvas = ImageDraw.Draw(thisScreen)
thisSize = thisScreen.size
# print(thisSize)
thisCanvas.text((5,10), "Server Running", fill=penColor, align ="left")
thisCanvas.text((5,20),f"Run Time: {inputTime:.1f}",fill=penColor, align ="left")
thisCanvas.text((thisSize[0]-40,0), "Exit:->",fill=penColor , align="right")
thisCanvas.text((thisSize[0]-60,50), "Invert:->",fill=penColor , align="right")
ms.display_image(thisScreen)
def broadcast_runTime():
global elapsed
while True:
sleep(1)
packet = {"time", elapsed}
print(packet)
myServer.broadcast(packet)
def broadcast_robot_state():
while True:
sleep(0.1)
myServer.broadcast(myRobot.state)
#Start Multi Threading Events
hub.threadpool.spawn(manageMiniScreen)
hub.threadpool.spawn(broadcast_runTime)
# hub.threadpool.spawn(broadcast_robot_state)
#Start Server
ms.display_text("Starting Server" )
myServer.serve_forever()
The manageMiniScreen Thread works and I can see my elapsed run time on the Mini screen and use the MiniScreen buttons.
My Terminal in Visual Studio Code has this output:
I am not Sure the broadcast_runTime is working.
I am not getting the Web server to display my custom pages correctly.
I created my own HTML file myTimeO.html which was based on the dashboard example:
<!DOCTYPE html>
{% extends "base-controller.html" %}
{% block head %}
{{ super() }}
{% endblock %}
{% block body %}
<header>
<h1>
Time Update?
</h1>
</header>
<main>
<table>
<thead>
<tr>
<th colspan="2">TIME!</th>
</tr>
</thead>
<tbody>
<tr>
<td>blank</td>
<td id="this_time">0</td>
</tr>
<tr>
<td>value</td>
<td id="time_value">0</td>
</tr>
</tbody>
</table>
</main>
<script>
subscribe((message) => {
const { time } = message;
document.getElementById("time_value").innerHTML = time;
});
</script>
{% endblock %}
Which when viewed at http://127.0.0.1:8070/myTimeO.html Displays:
My File does not seem to be extending the base blueprints correctly. Using developer tools the html generated does not have any links to java script files. as shown by this error:
So I looked through the blueprint file that is the default index.html served at http://127.0.0.1:8070 and found the scripting lines that are included there. I modified my HTML file to now be myTimeM.html:
<!DOCTYPE html>
{% extends "base-controller.html" %}
{% block head %}
{{ super() }}
<link rel="stylesheet" href="/base/index.css">
<link rel="stylesheet" href="/video/styles.css">
<script type="text/javascript" src="/messaging/pubsub.js"></script>
<script type="text/javascript" src="/webcomponents/vendor/nipplejs.min.js"></script>
<script type="text/javascript" src="/webcomponents/joystick-component.js"></script>
<link rel="stylesheet" href="styles.css"></link>
{% endblock %}
{% block body %}
<header>
<h1>
Time Update?
</h1>
</header>
<main>
<table>
<thead>
<tr>
<th colspan="2">TIME!</th>
</tr>
</thead>
<tbody>
<tr>
<td>blank</td>
<td id="this_time">0</td>
</tr>
<tr>
<td>value</td>
<td id="time_value">0</td>
</tr>
</tbody>
</table>
</main>
<script>
subscribe((message) => {
const { time } = message;
document.getElementById("time_value").innerHTML = time;
});
</script>
{% endblock %}
Which now views as:
I can see that the CSS is now applied, and comparing the sources, I now have the Js file is now loaded into my html:
But to do this I had to copy the code in. As the images show I seem to be having a problem with the extending of the Jinja templates. I should not see the {%extends … lines at the top of my pages. This webpage stays static and the value number is not changing. So I think somewhere my html pages are not correctly extending the blueprint templates and therefore are not currently able to respond to the broadcast_runTime event of the webserver.
So My current task is to try and get the value in the html table of the webserver to match the elapsed time value that is showing on the miniscreen.
Any help would be greatly appreciated.