实现web点灯功能其实也不难,我们先来写一下服务端的代码
1.1 实现点灯接口
通过Gin的文档,我们可以抄一个简单的参数解析代码,然后修改成我们需要的代码。
// 调用路径参考 /setLedValue?name=green&value=1
r.GET("/setLedValue", func(c *gin.Context) {
name := c.Query("name")
value := c.Query("value")
setLedValue(name, value)
c.JSON(http.StatusOK, gin.H{"status": "ok"})
})
这样就定义了一个超级简单的接口,通过传递name和value参数,然后调用设置led的函数,就完成这个功能了。
1.2 实现点灯函数
我们可以通过直接使用sysfs来完成点灯功能,这里我就偷懒一下,直接使用米尔T113板子上的两个已经配置好的led-green和led-blue。点灯函数如下
func setLedValue(name, value string) {
// Open the file for the specified LED
f, err := os.OpenFile("/sys/class/leds/"+Default.Leds[name].Path+"/brightness", os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
fmt.Println("open file error :", err)
return
}
defer f.Close()
// Write the new brightness value to the file
_, err = f.WriteString(value)
if err != nil {
fmt.Println(err)
return
}
}
在这里,为了能不修改代码,又可以快速配置板载 led灯,添加了toml文件配置led灯的功能。配置文件如下
hostname = ["milkv.local", "milkvt113.local"]
[leds.green]
port = 0
path = "led-green"
value = "1"
[leds.blue]
port = 0
path = "led-blue"
value = "1"
这个配置文件可以修改mDNS的域名(可以设置多个域名),以及led的设置,例如这里就添加了两个led,并设置了对应路径和默认状态。
读取配置文件的代码如下
package main
import (
"fmt"
"os"
"github.com/BurntSushi/toml"
)
var Default config
type (
config struct {
Hostname []string
Leds map[string]led
}
led struct {
Port int64
Path string
Value string
}
)
func getConfigs() {
f := "configs.toml"
_, err := toml.DecodeFile(f, &Default)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
可以正常调用
LED也正常点亮了
代码还有需要完善的地方,首先点灯函数没有对参数的有效性进行检查。我们可以将对应代码进行修改。
func setLedValue(name, value string) string {
if value == "1" || value == "0" {
for n := range Default.Leds {
if n == name {
// Open the file for the specified LED
f, err := os.OpenFile("/sys/class/leds/"+Default.Leds[name].Path+"/brightness", os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
fmt.Println("open file error :", err)
return err.Error()
}
defer f.Close()
// Write the new brightness value to the file
_, err = f.WriteString(value)
if err != nil {
fmt.Println(err)
return err.Error()
}
return "Led " + name + " set to " + value
}
}
return "Led " + name + " not found"
} else {
fmt.Println("value must be 0 or 1, got", value)
return "Value must be 0 or 1"
}
}
后端接口的代码也需要修改一下
// 调用路径参考 /setLedValue?name=green&value=1
r.GET("/setLedValue", func(c *gin.Context) {
name := c.Query("name")
value := c.Query("value")
c.JSON(http.StatusOK, gin.H{"status": setLedValue(name, value)})
})
然后启动的时候,在成功加载了配置文件后,对led的默认状态进行设置。
func main() {
getConfigs()
// 设置LED灯的默认状态
for n := range Default.Leds {
setLedValue(n, Default.Leds[n].Value)
}
go runDNS()
getInfo()
r := setupRouter()
// Listen and Server in 0.0.0.0:8080
r.Run(":80")
}
这样就好很多了,接下来,我们再来编写web端的界面代码,顺便学习一下Vue的组件书写方式。
我们先创建一个Led组件,在component目录下新建一个Led.vue文件。这个文件里需要先添加两个隐藏的button,因为Tailwind CSS会自动优化未使用的主题。有空我再找找别的办法来解决这个问题。
<template>
<h1 class="m-1 p-1"> LED : {{ name }} <span class="float-right"><button class="rounded-md p-1 px-10 text-white"
:class="[status === 'on' ? 'bg-' + name + '-600' : 'bg-gray-700']" @click="setLedStatus">{{ status
}}</button></span>
</h1>
<button class="hidden bg-green-600" />
<button class="hidden bg-blue-600" />
</template>
<script setup lang="ts">
import axios from 'axios'
import { ref } from 'vue'
const status = ref('on')
const props = defineProps<{
name?: string
value?: string
}>()
if (props.value === 'off') {
status.value = 'off'
}
function setLedStatus() {
axios.get('/setLedValue?name=' + props.name + '&value=' + (status.value === "on" ? "1" : "0")).then((res) => {
console.log(res.data)
let str = res.data.status.toString()
if (str.includes("set to")) {
if (str.slice(-1) === "1") { status.value = "off" } else {
status.value = "on"
}
}
})
}
</script>
然后在devices.vue文件里,添加相关的组件。
<template>
<div class="m-4 p-2 rounded-md bg-slate-200 text-gray-800 w-9/12 text-sm">
<Led name="green" value="off" />
<Led name="blue" value="off" />
</div>
</template>
<script setup lang="ts">
//import axios from 'axios'
import { onMounted, ref } from 'vue'
import Led from "../components/Led.vue"
const BoardList = ref(0)
BoardList.value = 0
onMounted(() => {
})
</script>
然后我们就可以在页面上,直接控制LED的亮和灭啦。
更多回帖