at main 5.6 kB view raw
1package handler 2 3import ( 4 "fmt" 5 "image" 6 "io" 7 "strconv" 8 9 "github.com/gin-gonic/gin" 10 "tangled.org/cdbrdr.com/scrn/internal/display" 11) 12 13const ( 14 width = 800 15 height = 480 16 padding = 6 17 split = width * 0.6 18) 19 20type section struct { 21 rect image.Rectangle 22} 23 24type APIHandler struct { 25 display *display.Display 26} 27 28func NewAPIHandler(display *display.Display) *APIHandler { 29 return &APIHandler{ 30 display, 31 } 32} 33 34func (h *APIHandler) HandleGroup(group *gin.RouterGroup) { 35 group.GET("/setup", h.handleSetup) 36 group.GET("/display", h.handleDisplay) 37 group.GET("/image.bmp", h.handleImage) 38 group.POST("/log", h.handleLog) 39} 40 41func (h *APIHandler) handleLog(c *gin.Context) { 42 buf, err := io.ReadAll(c.Request.Body) 43 if err != nil { 44 fmt.Println(err) 45 return 46 } 47 fmt.Println(string(buf)) 48} 49 50type setupResponse struct { 51 Status int `json:"status"` 52 ApiKey *string `json:"api_key"` 53 FriendlyID *string `json:"friendly_id"` 54 ImageURL *string `json:"image_url"` 55 Filename string `json:"filename,omitempty"` 56 Message string `json:"message,omitempty"` 57} 58 59// Handle /api/setup. 60// Response: 61// 62// { 63// "status": 200, 64// "api_key": "2r--SahjsAKCFksVcped2Q", 65// "friendly_id": "917F0B", 66// "image_url": "https://usetrmnl.com/images/setup/setup-logo.bmp", 67// "filename": "empty_state" 68// } 69 70// or 71// 72// { 73// "status": 404, 74// "api_key": null, 75// "friendly_id": null, 76// "image_url": null, 77// "message": "MAC Address not registered" 78// } 79func (h *APIHandler) handleSetup(c *gin.Context) { 80 81 mac := c.Request.Header.Get("ID") 82 if mac == "" { 83 c.JSON(200, &setupResponse{ 84 Status: 404, 85 Message: "MAC address missing", 86 }) 87 return 88 } 89 90 apiKey := "abcdf" 91 friendlyID := mac 92 c.JSON(200, &setupResponse{ 93 Status: 200, 94 ApiKey: &apiKey, 95 FriendlyID: &friendlyID, 96 }) 97} 98 99type displayResponse struct { 100 Status int `json:"status"` 101 ImageURL string `json:"image_url"` 102 Filename string `json:"filename"` 103 RefreshRate int `json:"refresh_rate"` 104 SpecialFunction string `json:"special_function"` 105} 106 107// Response: 108// 109// { 110// "status": 0, 111// "image_url": "https://...", 112// "filename": "mashup-2024-12-29T16-38-16Z-28d21f.bmp", 113// "refresh_rate": 907, 114// "reset_firmware": false, 115// "update_firmware": true, 116// "firmware_url": "https://trmnl.s3.us-east-2.amazonaws.com/FW1.4.5.bin", 117// "special_function": "identify" 118// } 119func (h *APIHandler) handleDisplay(c *gin.Context) { 120 fmt.Println(c.Request.Header) 121 122 c.JSON(200, &displayResponse{ 123 Status: 0, 124 ImageURL: "http://192.168.0.238:8081/api/image.bmp", 125 Filename: "image.bmp", 126 RefreshRate: 60, 127 SpecialFunction: "identify", 128 }) 129} 130 131func (h *APIHandler) handleImage(c *gin.Context) { 132 fmt.Println(c.Request.Header) 133 134 img, err := h.display.RenderBMP() 135 if err != nil { 136 fmt.Println(err) 137 c.AbortWithStatus(500) 138 return 139 } 140 141 c.Header("Content-Length", strconv.Itoa(len(img))) 142 c.Data(200, "image/bmp", img) 143 144 // img := image.NewPaletted(image.Rect(0, 0, 800, 480), color.Palette{color.White, color.Black}) 145 146 // // ctx := draw2dimg.NewGraphicContextWithPainter(img, util.NewPalettedPainter(img)) 147 148 // for _, section := range h.sections { 149 // // Create a new sub image for the section 150 // sub := (img.SubImage(section.rect)).(*image.Paletted) 151 // // Fill it with white background 152 // draw.Draw(sub, sub.Bounds(), image.NewUniform(color.White), image.Pt(0, 0), draw.Over) 153 // // Create a draw2dimg context to pass on to the module 154 // subc := draw2dimg.NewGraphicContextWithPainter(sub, util.NewPalettedPainter(sub)) 155 156 // // Draw using the module 157 // if err := section.module.Draw(subc); err != nil { 158 // fmt.Println(err) 159 // continue 160 // } 161 162 // area := image.Rect( 163 // sub.Rect.Min.X+20, 164 // sub.Rect.Min.Y+30, 165 // sub.Rect.Min.X+30, 166 // sub.Rect.Min.Y+110, 167 // ) 168 // draw.Draw(sub, area, util.NewGrayImage(), image.Pt(0, 0), draw.Over) 169 // } 170 171 // // Draw separator 172 // // ctx.SetStrokeColor(color.Black) 173 // // ctx.SetLineWidth(1) 174 // // ctx.SetLineDash([]float64{2, 15}, 0) 175 // // ctx.SetLineCap(draw2d.ButtCap) 176 // // ctx.MoveTo(split, 100) 177 // // ctx.LineTo(split, height-100) 178 // // ctx.Stroke() 179 180 // p := int(height * 0.2) 181 182 // for i := p; i < height-p; i += 6 { 183 // img.Set(split, i, color.Black) 184 // } 185 186 // // split := width * 0.6 187 188 // // left := img.SubImage(image.Rect( 189 // // padding, 190 // // padding, 191 // // int(split)-(padding/2), 192 // // height-padding, 193 // // )) 194 // // limg := util.NewRoundedImage(left.(*image.Paletted), 10) 195 196 // // right := img.SubImage(image.Rect( 197 // // int(split)+(padding/2), 198 // // padding, 199 // // width-padding, 200 // // height-padding, 201 // // )) 202 // // rimg := util.NewRoundedImage(right.(*image.Paletted), 10) 203 204 // // sect := (img.SubImage(image.Rect( 205 // // int(split)+(padding/2)+20, 206 // // padding+20, 207 // // int(split)+(padding/2)+30, 208 // // padding+110, 209 // // ))).(*image.Paletted) 210 211 // // draw.Draw(limg, limg.Bounds(), image.NewUniform(color.White), image.Pt(0, 0), draw.Over) 212 // // draw.Draw(rimg, rimg.Bounds(), image.NewUniform(color.White), image.Pt(0, 0), draw.Over) 213 // // draw.Draw(sect, sect.Bounds(), util.NewGrayImage(), image.Pt(0, 0), draw.Over) 214 215 // data := bytes.NewBuffer([]byte{}) 216 // bmp.Encode(data, img) 217 // buf := data.Bytes() 218 // // Fix some header values so that trmnl is happy 219 // buf[46] = 2 220 // buf[57] = 0 221 // buf[61] = 0 222 223 // c.Header("Content-Length", strconv.Itoa(len(buf))) 224 // c.Data(200, "image/bmp", buf) 225}