Skip to content

Commit 7a52041

Browse files
committed
initial commit
1 parent ab85819 commit 7a52041

Some content is hidden

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

66 files changed

+3239
-2
lines changed

Pipfile

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[[source]]
2+
name = "pypi"
3+
url = "https://pypi.org/simple"
4+
verify_ssl = true
5+
6+
[dev-packages]
7+
8+
[packages]
9+
kivy = "*"
10+
11+
[requires]
12+
python_version = "3.8"

README.md

+36-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,36 @@
1-
# headunit-ui
2-
A head unit UI designed to replace the RTx/SMEG/RNEG/NG4/RCC/NAC
1+
# HeadUnit UI
2+
3+
## Intro
4+
5+
This is the UI part of a headunit project from OpenLeo, based on python and kivy
6+
7+
## Design (and integration in the whole head unit project)
8+
9+
This should be launched last, and ideally (not there yet), it should only interface to the other components of the headunit system, not directly to CAN/VAN and devices. A watchdog system (with the UI sending a heartbeat to the OS) would be ideal, as this could then be used to reload the UI should a crash happen.
10+
11+
The UI is based on a core that is basically the home screen + the app bar + launching apps and giving them context (and ideally, custom widgets to have a coherent style across all apps). All the actual features are in "apps", which are actually python modules.
12+
13+
14+
## Apps design rules
15+
16+
* You can test your apps without launching the whole UI by running the app as a module (eg. with it's `__main__.py`)
17+
* You should avoid multiple menus and submenus, keep it simple, it is used while driving!
18+
* You should only interface with the car and devices thru what the headunit and UI provides. some apps may require direct connection (for example a diagnostics app that would need direct connection to CAN), but if you happens to connect directly to something, it is more likely that the actual need would be to add a component to the head unit OS instead.
19+
* Dependencies should be self contained, if possible.
20+
* Two icons are needed: `icon.png` for the menu and `sc_icon.png` for the shortcut in app bar
21+
22+
## FAQ
23+
24+
* **Why using python and kivy for an embedded project?** Because it was the best compromise between being easy to work with, without licencing nightmare, and still being able to work directly on a framebuffer (kivy being SDL2 based, you can run it without X11 or Wayland).
25+
* **Why only the UI?** Because it makes the whole head unit more reliable, if the UI crashes, it wouldn't lose CAN frames or the music being played, and the embedded linux can then detect and reload the UI only, which should make it safer as it wouldn't distract as much while driving.
26+
* **Is this PSA/Leo only?** Actually, the whole head unit design is made so it should be possible to port it for any other car architecture, even if these aren't the focus of OpenLeo.
27+
*
28+
29+
## TODO
30+
31+
* Give the apps context so they can interface with the car (can bus for telematics, climate control, and the like)
32+
* Also give context for the other components of the head unit (music playback, navigation, bluetooth...)
33+
* Have a basic (eg. turn by turn symbols) navigation
34+
* Have working apps...
35+
* Add custom widgets that follow a common OpenLeo design guiderules set
36+
* Inject constant infos to apps (car make, model, version, etc)

android.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
title=HeadUnit
2+
author=openleo
3+
orientation=landscape

apps.kv

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<AppsScreen>:
2+
GridLayout:
3+
id: apps_grid
4+
cols: 5
5+
rows: 4
6+
padding: 30
7+
spacing: 50, 30
8+
size_hint: 1, 1
9+
canvas.before:
10+
Color:
11+
rgb: 0,0,0
12+
Rectangle:
13+
pos: self.pos
14+
size: self.size

apps/__init__.py

Whitespace-only changes.

apps/climate_control/__init__.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import os
2+
from kivy.app import App
3+
from kivy.lang import Builder
4+
from kivy.uix.label import Label
5+
from kivy.uix.screenmanager import Screen
6+
7+
_app_name_ = 'climate_control'
8+
9+
class climate_controlApp(Screen):
10+
def __init__(self, **kwargs):
11+
super(climate_controlApp, self).__init__(**kwargs)
12+
self.name = _app_name_
13+
self.root = App.get_running_app().root
14+
self.dir = dirname = os.path.dirname(__file__)
15+
16+
layout = Builder.load_file("{}/climate.kv".format(self.dir))
17+
self.add_widget(layout)

apps/climate_control/__main__.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import __init__ as app
2+
from kivy.app import App
3+
from kivy.uix.screenmanager import ScreenManager
4+
5+
global sub_app
6+
7+
class SubApp(App):
8+
def build(self):
9+
sm = ScreenManager(id='sm')
10+
sm.add_widget(sub_app())
11+
return sm
12+
13+
if __name__ =='__main__':
14+
sub_app = getattr(app, '{}App'.format(app._app_name_))
15+
SubApp().run()

apps/climate_control/climate.kv

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
FloatLayout:
2+
size_hint: 1, 1
3+
# Main layout
4+
BoxLayout:
5+
orientation: 'vertical'
6+
7+
BoxLayout
8+
orientation: 'horizontal'
9+
size_hint: 1, 0.2
10+
#ToggleButton:
11+
# text: 'AutoL'
12+
ToggleButton:
13+
text: 'Front defrost'
14+
ToggleButton:
15+
text: 'Rear defrost'
16+
ToggleButton:
17+
text: 'Auto'
18+
ToggleButton:
19+
text: 'AC'
20+
ToggleButton:
21+
text: 'Recycling'
22+
#ToggleButton:
23+
# text: 'AutoR'
24+
25+
26+
BoxLayout:
27+
orientation: 'horizontal'
28+
29+
# Left seat control
30+
BoxLayout:
31+
orientation: 'vertical'
32+
size_hint: 0.4, 1
33+
Button:
34+
text: 'Temp +1'
35+
Label:
36+
text: '25c'
37+
Button:
38+
text: 'Temp -1'
39+
40+
BoxLayout:
41+
orientation: 'vertical'
42+
size_hint: 0.4, 1
43+
ToggleButton:
44+
text: 'U'
45+
ToggleButton:
46+
text: 'M'
47+
ToggleButton:
48+
text: 'D'
49+
50+
# Common controls
51+
BoxLayout:
52+
orientation: 'vertical'
53+
54+
#BoxLayout:
55+
# orientation: 'horizontal'
56+
# ToggleButton:
57+
# text: 'D'
58+
# ToggleButton:
59+
# text: 'M'
60+
# ToggleButton:
61+
# text: 'U'
62+
63+
AnchorLayout:
64+
size_hint: 1, 1
65+
BoxLayout:
66+
orientation: 'horizontal'
67+
size_hint: 0.9, 0.2
68+
ToggleButton:
69+
text: 'F1'
70+
ToggleButton:
71+
text: 'F2'
72+
ToggleButton:
73+
text: 'F3'
74+
ToggleButton:
75+
text: 'F4'
76+
ToggleButton:
77+
text: 'F5'
78+
ToggleButton:
79+
text: 'F6'
80+
ToggleButton:
81+
text: 'F7'
82+
ToggleButton:
83+
text: 'F8'
84+
85+
# Right seat control
86+
BoxLayout:
87+
orientation: 'vertical'
88+
size_hint: 0.4,1
89+
ToggleButton:
90+
text: 'U'
91+
ToggleButton:
92+
text: 'M'
93+
ToggleButton:
94+
text: 'D'
95+
BoxLayout:
96+
orientation: 'vertical'
97+
size_hint: 0.4, 1
98+
Button:
99+
text: 'Temp +1'
100+
Label:
101+
text: '25c'
102+
Button:
103+
text: 'Temp -1'

apps/climate_control/climate_207.kv

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
FloatLayout:
2+
size_hint: 1, 1
3+
# Main layout
4+
BoxLayout:
5+
orientation: 'horizontal'
6+
7+
# Left seat control
8+
BoxLayout:
9+
orientation: 'vertical'
10+
size_hint: 0.4, 1
11+
Button:
12+
text: 'Temp +1'
13+
Label:
14+
text: '25c'
15+
Button:
16+
text: 'Temp -1'
17+
18+
# Common controls
19+
BoxLayout:
20+
orientation: 'vertical'
21+
22+
BoxLayout:
23+
orientation: 'horizontal'
24+
ToggleButton:
25+
text: 'ON'
26+
ToggleButton:
27+
text: 'D'
28+
ToggleButton:
29+
text: 'M'
30+
ToggleButton:
31+
text: 'U'
32+
ToggleButton:
33+
text: 'D+M'
34+
ToggleButton:
35+
text: 'D+U'
36+
37+
BoxLayout:
38+
orientation: 'horizontal'
39+
ToggleButton:
40+
text: 'Front defrost'
41+
ToggleButton:
42+
text: 'Rear defrost'
43+
ToggleButton:
44+
text: 'AC'
45+
ToggleButton:
46+
text: 'Recycling'
47+
48+
BoxLayout:
49+
orientation: 'horizontal'
50+
ToggleButton:
51+
text: 'Auto'
52+
ToggleButton:
53+
text: 'F1'
54+
ToggleButton:
55+
text: 'F2'
56+
ToggleButton:
57+
text: 'F3'
58+
ToggleButton:
59+
text: 'F4'
60+
ToggleButton:
61+
text: 'F5'
62+
ToggleButton:
63+
text: 'F6'
64+
ToggleButton:
65+
text: 'F7'
66+
ToggleButton:
67+
text: 'F8'
68+
69+
# Right seat control
70+
BoxLayout:
71+
orientation: 'vertical'
72+
size_hint: 0.4, 1
73+
Button:
74+
text: 'Temp +1'
75+
Label:
76+
text: '25c'
77+
Button:
78+
text: 'Temp -1'

apps/climate_control/img/icon.png

18.4 KB
Loading

apps/climate_control/img/sc_icon.png

3.19 KB
Loading

apps/music/__init__.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from kivy.app import App
2+
from kivy.lang import Builder
3+
from kivy.uix.label import Label
4+
from kivy.uix.button import Button
5+
from kivy.uix.screenmanager import Screen
6+
import os
7+
8+
_app_name_ = 'music'
9+
10+
class musicApp(Screen):
11+
def __init__(self, **kwargs):
12+
super(musicApp, self).__init__(**kwargs)
13+
self.name = _app_name_
14+
self.root = App.get_running_app().root
15+
self.dir = dirname = os.path.dirname(__file__)
16+
layout = Builder.load_file("{}/music.kv".format(self.dir))
17+
layout.ids['background'].source = '{}/img/background.png'.format(self.dir)
18+
19+
layout.ids['album_art'].source = '{}/img/album.png'.format(self.dir)
20+
21+
22+
for i in range(1, 100):
23+
playlist = Button(text='Playlist {}'.format(i), size_hint_y=None)
24+
layout.ids['playlists_list'].add_widget(playlist)
25+
self.add_widget(layout)

apps/music/__main__.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import __init__ as app
2+
from kivy.app import App
3+
from kivy.uix.screenmanager import ScreenManager
4+
5+
global sub_app
6+
7+
class SubApp(App):
8+
def build(self):
9+
sm = ScreenManager(id='sm')
10+
sm.add_widget(sub_app())
11+
return sm
12+
13+
if __name__ =='__main__':
14+
sub_app = getattr(app, '{}App'.format(app._app_name_))
15+
SubApp().run()

apps/music/img/album.png

15.2 KB
Loading

apps/music/img/background.png

19.6 KB
Loading

apps/music/img/icon.png

13.3 KB
Loading

apps/music/img/sc_icon.png

1.33 KB
Loading

0 commit comments

Comments
 (0)