Compare commits

...

11 Commits

Author SHA1 Message Date
yuno 399a8fa5b7 Delete 'wifi-opendock simple remote.py' 2023-06-27 13:47:52 +00:00
yuno 9e27dc59fe Delete 'wifi-opendock adv controles.py' 2023-06-27 13:47:41 +00:00
yuno 894e6da897 Upload files to '' 2023-06-27 13:47:22 +00:00
yuno b4f16a0468 Upload files to 'pcb files' 2022-07-15 23:33:18 +00:00
yuno 5115aa179a Upload files to '' 2022-07-12 21:04:43 +00:00
yuno db6216a6bc Update 'wifi-opendock simple remote.py' 2022-07-12 21:02:28 +00:00
yuno a382866c4a Update 'wifi-opendock.py' 2022-07-11 23:47:32 +00:00
yuno 38854b6122 Update 'wifi-opendock.py'
removed my wifi info
2022-07-11 23:08:03 +00:00
yuno 691c6af0ef Update 'wifi-opendock.py' 2022-07-11 22:43:11 +00:00
yuno 6549041895 Delete 'opendock.py' 2022-07-11 22:31:09 +00:00
yuno fadd940816 Upload files to '' 2022-07-11 22:30:32 +00:00
5 changed files with 352 additions and 16 deletions

116
index.html Normal file
View File

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<style>
@font-face {font-family: 'ChicagoFont';src: url('https://dangasson.github.io/Resources/Fonts/ChicagoFLF.ttf') format('truetype');font-weight: normal;font-style: normal;}.centered {top: 50%;left: 50%;transform: translate(-50%, -50%);}.container {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);}.ipod {width: 415px;height: 692px;border: 1px solid transparent;border-radius: 38px;background: linear-gradient(45deg, #E3E4E5, #FFFFFF);box-shadow: inset 5px -5px 15px 0px grey;}.ipod.small {transform: scale(0.67, 0.67);}.screen {position: relative;margin: 30px auto 0px auto;width: 284px;height: 230px;background: linear-gradient(135deg, #A5A59B, #D6D5D0);border-radius: 10px;box-shadow: inset 0px 0px 10px 2px #4D4D4D;font-family: "ChicagoFont", "Arial";font-size: 130%;color: #484647;}.title {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);}.title-bar {position: absolute;left: 5px;right: 5px;height: 16%;border-bottom: 2px solid #484647;text-align: center;}.play-icon {position: absolute;display: inline-block;top: 50%;left: 10px;transform: translate(0, -50%);border-left: 18px solid #484647;border-top: 9px solid transparent;border-bottom: 9px solid transparent;height: 0;width: 0;}.battery {position: absolute;right: 5px;height: 50px;width: 100px;background-color: #C1C1BA;border: 5px solid #484647;}.battery:before {content: '';position: absolute;top: 50%;right: -12px;transform: translate(0, -50%);height: 33%;width: 7px;background-color: #C1C1BA;border-right: 5px solid #484647;border-top: 5px solid #484647;border-bottom: 5px solid #484647;}.battery:after {content: '';position: absolute;top: 5px;bottom: 5px;left: 5px;width: 70px;background: repeating-linear-gradient(to right, #484647, #484647 20px, #C1C1BA 20px, #C1C1BA 25px, #484647 25px, #484647 45px, #C1C1BA 45px, #C1C1BA 50px, #484647 50px, #484647 70px);}.battery.small {transform: scale(0.3, 0.3);transform-origin: 100% 25%;}.menu-options {display: flex;flex-direction: column;justify-content: space-around;position: relative;top: 17%;height: 81%;}.option {padding-left: 12px;}.option:after {content: '';position: absolute;right: 18px;border-bottom: 3px solid #484647;border-right: 3px solid #484647;width: 8px;height: 8px;transform: rotate(-45deg) skew(7deg, 7deg);transform-origin: 180%;}.option.selected {background-color: #484647;border-bottom: 2px solid #484647;color: #C1C1BA;}.option.selected:after {border-bottom: 3px solid #C1C1BA;border-right: 3px solid #C1C1BA;}.outer-ring {position: relative;margin: 0 auto;top: 30px;height: 350px;width: 350px;border-radius: 50%;background-color: #FFFFFF;box-shadow: inset 5px -5px 30px -7px #595959;}.outer-ring:before, .outer-ring:after {content: '';position: absolute;width: 0;height: 99%;border: 1px solid #4D4D4D;}.outer-ring:before {left: 50%;transform: rotate(45deg);}.outer-ring:after {top: 0;left: 50%;transform: rotate(135deg);}.touch-wheel {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);height: 276px;width: 276px;border: 2px solid #4D4D4D;border-radius: 50%;background: radial-gradient(farthest-side at 90% -70%, #999999, #F2F2F2);box-shadow: 5px -5px 30px -7px #595959;z-index: 1;}.center-button {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);height: 100px;width: 100px;border: 2px solid #BABDC1;border-radius: 50%;background-color: #CBCCCE;background: radial-gradient(farthest-side at -90% 80%, #999999, #F2F2F2);}text {font-family: "Arial";font-size: 110%;font-weight: bold;fill: #BABDC1;}path {fill: transparent;}.skip {position: absolute;top: 50%;transform: translate(0, -50%);background-color: #BABDC1;height: 12px;width: 4px;}.skip:before, .skip:after {content: '';position: absolute;border-left: 9px solid #BABDC1;border-top: 6px solid transparent;border-bottom: 6px solid transparent;}.skip:before {left: -9px;}.skip:after {left: -18px;}.skip.forward {right: 7px;}.skip.back {left: 7px;transform: rotate(180deg) translate(0, 50%);}.play-pause {position: absolute;bottom: 12px;left: 50%;height: 0;width: 0;transform: translate(-13px, 0);border-left: 12px solid #BABDC1;border-top: 6px solid transparent;border-bottom: 6px solid transparent;}.play-pause:before {content: '';position: absolute;bottom: -6px;left: 4px;height: 12px;width: 10px;background: repeating-linear-gradient(to right, #BABDC1, #BABDC1 4px, transparent 4px, transparent 6px, #BABDC1 6px, #BABDC1 10px);}_:-ms-lang(x), .ipod {box-shadow: inset 5px -5px 25px 3px #999999;}_:-ms-lang(x), .screen {box-shadow: inset 0px 0px 20px 1px #595959;}_:-ms-lang(x), .outer-ring {box-shadow: inset 5px -5px 50px -7px #999999;}_:-ms-lang(x), .touch-wheel {box-shadow: 5px -5px 50px -7px #999999;}
</style>
<script>
function action(name) {
fetch("/?pod="+name)
}
function Touchwheel(selector) {
this.elem = document.querySelector(selector);
this.calc_pos = (ev) => {
let w = ev.target.clientWidth;
let h = ev.target.clientHeight;
let x = ev.offsetX / w - 0.5;
let y = ev.offsetY / h - 0.5;
let d = (Math.atan2(y, x) * (180 / Math.PI)) + 90;
return d;
}
this.last_pos = null;
this.last_seg = 0;
this.down_time = null;
this.mousedown = (ev) => {
if(ev.target != this.elem) return;
this.last_pos = this.calc_pos(ev);
this.down_time = ev.timeStamp;
}
this.mouseup = (ev) => {
if(ev.target != this.elem) return;
this.last_pos = null;
if(ev.type == "mouseup") {
let dt = ev.timeStamp - this.down_time;
if(dt < 100) {
console.log("clicked");
if(ev.offsetY / ev.target.clientHeight < 0.5) {
action("scrollup")
} else {
action("scrolldown")
}
}
}
}
this.mousemove = (ev) => {
if(ev.target != this.elem) return;
if(this.last_pos === null) return;
let pos = this.calc_pos(ev) - this.last_pos;
let seg = Math.round(pos / 16);
if(seg != this.last_seg) {
console.log(seg);
if(seg > this.last_seg) {
action("volup");
} else if(seg < this.last_seg) {
action("voldown");
}
this.last_seg = seg;
}
}
this.elem.onmousedown = this.mousedown;
this.elem.onmousemove = this.mousemove;
this.elem.onmouseup = this.mouseup;
this.elem.onmouseleave = this.mouseup;
}
</script>
</head>
<body>
<div class="container">
<div class="ipod small">
<div class="screen">
<div class="title-bar">
<div class="play-icon"></div>
<div class="title">iPod</div>
<div class="battery small"></div>
</div>
<div class="menu-options">
<div class="option">Playlists</div>
<div class="option">Artists</div>
<div class="option selected">Songs</div>
<div class="option">Settings</div>
<div class="option">About</div>
<div class="option">Now Playing</div>
</div>
</div>
<div class="outer-ring">
<svg viewBox="-150 5 350 350">
<path id="curve" d="m0,30 c16,-4 32,-4 48,0" />
<text onclick="action('menu')">
<textPath xlink:href="#curve">menu</textPath>
</text>
</svg>
<div class="skip forward" onclick="action('next')"></div>
<div class="skip back" onclick="action('prev')"></div>
<div class="play-pause" onclick="action('play')"></div>
<div class="touch-wheel">
<div class="center-button" onclick="action('ok')"></div>
</div>
</div>
</div>
</div>
<script>
const touchwheel = new Touchwheel(".touch-wheel");
</script>
<a href="/config.html">Config
</body>
</html>

236
main.py Normal file
View File

@ -0,0 +1,236 @@
from machine import Pin
from machine import UART
import network
import time
import socket
# config option
network.hostname("opendocks.local")
ui = "index.html"
config = "config.html"
port = 80 #dont change this shit brakes
# ssid and pass
ssid = 'kainet'
password = 'peepeepoopoo'
page = open(ui, "r")
html = page.read()
# aap commands start here
class Modes:
Switch = 0x00
Voice = 0x01
Simple = 0x02
Request = 0x03
AiR = 0x04
_test_sw_mode_simple = [0xFF, 0x55, 0x03, 0x00, 0x01, 0x02, 0xFA]
_test_button_up = [0xFF, 0x55, 0x03, 0x02, 0x00, 0x00, 0xFB]
_test_play = _test_sw_mode_simple + [0xFF, 0x55, 0x03, 0x02, 0x00, 0x01, 0xFA] + _test_button_up
# generate a checksum for a request
def req_checksum(length, mode, command, parameter):
return 0x100 - ((length + mode + sum(int(a) for a in command) + sum(int(a) for a in parameter)) & 0xff)
def make_request(mode: int, command: list[int], parameter=[]):
length = 1+len(command)+len(parameter)
ret = []
if mode != Modes.Switch: # add mode switch
ret += make_request(0, [0x01, mode])
ret += [0xFF, 0x55, length, mode] + command + parameter + [req_checksum(length, mode, command, parameter)]
if mode == Modes.Simple: # add button up
ret += [0xFF, 0x55, 0x03, 0x02, 0x00, 0x00, 0xFB] # button up
return ret
class Requests:
#ButtonReleased = make_request(Modes.Simple, [0x0, 0x0])
PlayToggle = make_request(Modes.Simple, [0x0, 0x01])
VolUp = make_request(Modes.Simple, [0x0, 0x02])
VolDown = make_request(Modes.Simple, [0x0, 0x04])
Next = make_request(Modes.Simple, [0x0, 0x08])
Prev = make_request(Modes.Simple, [0x0, 0x10])
NextAlbum = make_request(Modes.Simple, [0x0, 0x20])
PrevAlbum = make_request(Modes.Simple, [0x0, 0x40])
Stop = make_request(Modes.Simple, [0x0, 0x80])
Play = make_request(Modes.Simple, [0x0, 0x0, 0x01])
Pause = make_request(Modes.Simple, [0x0, 0x0, 0x02])
MuteToggle = make_request(Modes.Simple, [0x0, 0x0, 0x04])
NextPlaylist = make_request(Modes.Simple, [0x0, 0x0, 0x20])
PrevPlaylist = make_request(Modes.Simple, [0x0, 0x0, 0x40])
ShuffleToggle = make_request(Modes.Simple, [0x0, 0x0, 0x80])
RepeatToggle = make_request(Modes.Simple, [0x0, 0x0, 0x0, 0x01])
Off = make_request(Modes.Simple, [0x0, 0x0, 0x0, 0x04])
On = make_request(Modes.Simple, [0x0, 0x0, 0x0, 0x08])
Menu = make_request(Modes.Simple, [0x0, 0x0, 0x0, 0x40])
Ok = make_request(Modes.Simple, [0x0, 0x0, 0x0, 0x80])
ScrollUp = make_request(Modes.Simple, [0x0, 0x0, 0x0, 0x0, 0x01])
ScrollDown = make_request(Modes.Simple, [0x0, 0x0, 0x0, 0x0, 0x02])
assert Requests.PlayToggle == _test_play, "invalid make_request"
# aap commands end here
"""
class AiRRequests:
GetIpodName = make_request(Modes.AiR, [0x0, 0x14])
def read_response(uart):
head = uart.read(2 + 1)
length = int(head[2])
packet = uart.read(length)
mode = packet[0]
command = [int(a) for a in packet[1:3]]
param = packet[3:-1]
return command, param
class AiR:
@staticmethod
def GetIpodName(uart):
uart.write(bytes(AiRRequests.GetIpodName))
command, param = read_response(uart)
assert command == [0x0, 0x15]
assert len(param) == 1
name = uart.read(int.from_bytes(param, 'little'))
return name.decode("utf8")
"""
class IPOD:
def __init__(self, uart) -> None:
self.uart = uart
def _cmd(self, cmd: list[int]):
self.uart.write(bytes(cmd))
def play(self): self._cmd(Requests.PlayToggle)
def next(self): self._cmd(Requests.Next)
def prev(self): self._cmd(Requests.Prev)
def menu(self): self._cmd(Requests.Menu)
def ok(self): self._cmd(Requests.Ok)
def volup(self): self._cmd(Requests.VolUp)
def voldown(self): self._cmd(Requests.VolDown)
def scrollup(self): self._cmd(Requests.ScrollUp)
def scrolldown(self): self._cmd(Requests.ScrollDown)
def init():
led = Pin("LED", Pin.OUT, value=1)
# network.hostname("opendock.local")
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.config(pm = 0xa11140) # Diable powersave mode
wlan.connect(ssid, password)
name = wlan.config("hostname")
# wlan.ifconfig(('192.168.1.69', '255.255.255.0', '192.168.1.5', '192.168.1.5'))
print("hostname is: " + name)
def blink_led(frequency = 0.5, num_blinks = 3):
for _ in range(num_blinks):
led.on()
time.sleep(frequency)
led.off()
time.sleep(frequency)
# Wait for connect or fail
max_wait = 10
while max_wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('waiting for connection...')
time.sleep(1)
# Handle connection error
if wlan.status() != 3:
blink_led(0.2, 5)
raise RuntimeError('wifi connection failed')
else:
blink_led(1, 2)
print('connected')
status = wlan.ifconfig()
print('ip = ' + status[0], ':' ,port ,sep ='')
def main():
# Open socket
addr = socket.getaddrinfo('0.0.0.0', port)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('listening on', addr)
uart = UART(0, 19200)
uart.init(19200, bits=8, parity=None, stop=1)
ipod = IPOD(uart)
ipod._cmd(_test_play)
actions = {
"play": ipod.play,
"next": ipod.next,
"prev": ipod.prev,
"volup": ipod.volup,
"voldown": ipod.voldown,
"menu": ipod.menu,
"ok": ipod.ok,
"scrollup": ipod.scrollup,
"scrolldown": ipod.scrolldown
}
def nop():
pass
# Listen for connections
while True:
try:
cl, addr = s.accept()
print('Client connected from', addr)
r = cl.recv(16000)
lines = r.splitlines()
req = lines[0].decode("utf8").split(" ")
method = req[0]
path = req[1]
ver = req[2]
print(f"method: {method} path: {path}")
_search = path.split("?")
if len(_search) > 1:
search = _search[1]
print(f"search: {search}")
for param in search.split("&"):
k,v = param.split("=")
if k == "pod":
actions.get(v, nop)()
print(f"executed: {v}")
head = 'HTTP/1.0 200 OK\r\n'
head += "Content-type: text/html\r\n"
head += f"Content-Length: {len(html)}\r\n"
head += "\r\n"
off = 0
SEG_SIZE = 1024
while off < len(html):
cl.send(html[off:off+SEG_SIZE])
off += SEG_SIZE
cl.close()
except Exception as e:
print("Exception", e)
cl.close()
print('Connection closed')
init()
main()

View File

@ -1,16 +0,0 @@
#import crap
from machine import UART, Pin
# init ipod uart
uart = UART(0, 19200)
uart.init(19200, bits=8, parity=None, stop=1)
#command table
play = bytes([0xFF, 0x55, 0x03, 0x00, 0x01, 0x02, 0xFA, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x01, 0xFA, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x00, 0xFB])
next = bytes([0xFF, 0x55, 0x03, 0x00, 0x01, 0x02, 0xFA, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x08, 0xF3, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x00, 0xFB])
prev = bytes([0xFF, 0x55, 0x03, 0x00, 0x01, 0x02, 0xFA, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x10, 0xEB, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x00, 0xFB])
vup = bytes([0xFF, 0x55, 0x03, 0x00, 0x01, 0x02, 0xFA, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x02, 0xF9, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x00, 0xFB])
vdown = bytes([0xFF, 0x55, 0x03, 0x00, 0x01, 0x02, 0xFA, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x04, 0xF7, 0xFF, 0x55, 0x03, 0x02, 0x00, 0x00, 0xFB])
#code
uart.write(play) # it works yey

Binary file not shown.

BIN
pcb files/open dock.zip Normal file

Binary file not shown.