55from requests import Response
66from enum import Enum
77from typing import Any , Dict , Optional , List
8+ from time import sleep
89
910"""
1011 Small library to interact with a fluepdot controlled display
1112 https://fluepdot.readthedocs.io/en/latest/
1213
13- it should only be required to change the baseURL
14+ Usage:
15+ from fluepdot import Fluepdot
16+ fd = Fluepdot("http://module.local")
17+ fd.post_text("Hello World!")
1418
1519 Currently there is no support for changing the timings.
1620"""
@@ -38,11 +42,9 @@ def __init__(self, baseURL: str, width: int = 115, height: int = 16):
3842 self .height = height
3943 self .fonts : Optional [List [str ]] = None
4044
41-
4245 def set_url (self , url : str ):
4346 self .baseURL = url
4447
45-
4648 def post_time (self ) -> None :
4749 import datetime
4850 dt : str = ""
@@ -52,14 +54,12 @@ def post_time(self) -> None:
5254 dt = ndt
5355 self .post_text (dt , x = 8 , y = 1 , font = "fixed_7x14" )
5456
55-
5657 def get_size (self ) -> (int , int ):
5758 frame = self .get_frame ()
5859 self .width = len (frame [0 ])
5960 self .height = len (frame ) - 1
6061 return [self .width , self .height ]
6162
62-
6363 def get_frame (self ) -> List [str ]:
6464 r = self ._get (frameURL )
6565 return r .text .split ('\n ' )
@@ -70,25 +70,56 @@ def get_pixel(self, x: int = 0, y: int = 0) -> bool | None:
7070 rtn = True if r .text == "X" else False if r .text == " " else None
7171 return rtn
7272
73-
7473 def get_fonts (self ) -> None :
7574 r = self ._get (fontURL )
7675 fonts = r .text .split ("\n " )
7776 print (fonts )
7877
79-
8078 def get_mode (self ) -> Mode :
8179 r = self ._get (modeURL )
8280 return Mode (r .text )
8381
84-
8582 def post_text (self , text : str , x : int = 0 , y : int = 0 , font : str = "DejaVuSans12" ) -> Response :
8683 return self ._post (textURL , get = {"x" : x , "y" : y , "font" : font }, post = text )
8784
88-
8985 def post_frame_raw (self , frame : str ) -> Response :
9086 return self ._post (frameURL , post = frame )
9187
88+ def post_scroll_frame_raw (self , frame : str , loop :bool or int = False , sleep_time :int = 1 ) -> None :
89+ """
90+ Parameters
91+ ----------
92+ frame : str
93+ A " " and "X" encoded framestring exactly the length of and 16 lines high
94+ loop : bool or int, optional
95+ if int it will loop the frame with the given number of seperation spaces
96+ if bool:
97+ True: same as with loop=115
98+ False: will scroll the frame from right to left starting at blank and scrolling till blank
99+ sleep_time : int, optional
100+ The number of seconds to wait between steps, by default 1
101+ will be limited by the timing interval of the display
102+ """
103+ def _extend_frame (line : str ) -> str :
104+ return line + (" " * loop )+ line [0 :115 ]
105+ def _pad_frame (line : str ) -> str :
106+ pad = " " * 115
107+ return pad + line + pad
108+
109+ frame = frame .split ("\n " )
110+ length = len (frame [0 ])+ loop if type (loop ) == int else len (frame [0 ])+ 115
111+
112+ if type (loop ) == int :
113+ frame = list (map (_extend_frame , frame ))
114+ else :
115+ frame = list (map (_pad_frame , frame ))
116+
117+ _run_once = True
118+ while loop or type (loop )== int or _run_once :
119+ _run_once = False
120+ for i in range (0 , length , 2 ):
121+ self .post_frame_raw ("\n " .join (l [i :i + 115 ] for l in frame ))
122+ sleep (sleep_time )
92123
93124 def post_frame (self , frame : List [List [bool ]]) -> Response :
94125 data : List [List [str ]] = [[" " ] * width for _ in range (height )]
@@ -109,34 +140,30 @@ def set_pixel(self, x: int = 0, y: int = 0) -> Response:
109140 def unset_pixel (self , x : int = 0 , y : int = 0 ) -> Response :
110141 return self ._delete (pixelURL , get = {"x" : x , "y" : y })
111142
112-
113143 def set_mode (self , mode : Mode = Mode .FULL ) -> Response :
114144 return self ._put (modeURL , post = str (mode .value ))
115145
116-
117146 def _delete (self , endpoint : str , get : GetParam = {}, post : PostParam = '' ) -> Response :
118147 if self .baseURL == None :
119148 raise RuntimeError ('baseURL is None, call set_url' )
120149 return requests .delete (url = self .baseURL + endpoint , params = get )
121150
122-
123151 def _post (self , endpoint : str , get : GetParam = {}, post : PostParam = '' ) -> Response :
124152 if self .baseURL == None :
125153 raise RuntimeError ('baseURL is None, call set_url' )
126154 return requests .post (url = self .baseURL + endpoint , params = get , data = post )
127155
128-
129156 def _put (self , endpoint : str , get : GetParam = {}, post : PostParam = '' ) -> Response :
130157 if self .baseURL == None :
131158 raise RuntimeError ('baseURL is None, call set_url' )
132159 return requests .put (url = self .baseURL + endpoint , params = get , data = post )
133160
134-
135161 def _get (self , endpoint : str , get : GetParam = {}) -> Response :
136162 if self .baseURL == None :
137163 raise RuntimeError ('baseURL is None, call set_url' )
138164 return requests .get (url = self .baseURL + endpoint , params = get )
139165
140166
141167if __name__ == "__main__" :
142- pass
168+ fd = Fluepdot ("http://module.local" )
169+ fd .post_text ("Hello World!" )
0 commit comments