Skip to content

Commit

Permalink
dev: add raspberry gpio support
Browse files Browse the repository at this point in the history
  • Loading branch information
wwhai committed Mar 8, 2023
1 parent 0c3568b commit 6e2fffa
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 18 deletions.
5 changes: 4 additions & 1 deletion appstack/lua_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,10 @@ func LoadAppLib(app *typex.Application, e typex.RuleX) {
//------------------------------------------------------------------------
// 注册GPIO操作函数到LUA运行时
//------------------------------------------------------------------------
// EEKIT
addAppLib(app, e, "eekit", "GPIOGet", rulexlib.EEKIT_GPIOGet(e))
addAppLib(app, e, "eekit", "GPIOSet", rulexlib.EEKIT_GPIOSet(e))

// 树莓派4B
addAppLib(app, e, "raspi4b", "GPIOGet", rulexlib.RASPI4_GPIOGet(e))
addAppLib(app, e, "raspi4b", "GPIOSet", rulexlib.RASPI4_GPIOSet(e))
}
7 changes: 4 additions & 3 deletions archsupport/eekit_adda_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package archsupport
import (
"errors"
"fmt"
"log"
"os/exec"
)

Expand Down Expand Up @@ -67,13 +68,13 @@ func _EEKIT_GPIOInit(Pin string, EnDir string) {
cmd := fmt.Sprintf("echo %s > /sys/class/gpio/export", Pin)
_, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
fmt.Println(err.Error())
log.Println(err)
}
//gpio set direction
cmd = fmt.Sprintf("echo %s > /sys/class/gpio/gpio%s/direction", EnDir, Pin)
_, err = exec.Command("sh", "-c", cmd).Output()
if err != nil {
fmt.Println(err.Error())
log.Println(err)
}
}

Expand All @@ -86,7 +87,7 @@ func EEKIT_GPIOSet(pin, value int) (bool, error) {
cmd := fmt.Sprintf("echo %d > /sys/class/gpio/gpio%d/value", value, pin)
_, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
fmt.Println(err.Error())
log.Println(err)
}
v, e := EEKIT_GPIOGet(pin)
if e != nil {
Expand Down
2 changes: 1 addition & 1 deletion archsupport/eekit_adda_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package archsupport
*
*/

func EEKIT_GPIOSet(value, pin int) (bool, error) {
func EEKIT_GPIOSet(pin, value int) (bool, error) {
return false, nil
}
func EEKIT_GPIOGet(pin int) (int, error) {
Expand Down
98 changes: 98 additions & 0 deletions archsupport/raspberry4b_adda_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package archsupport

import (
"errors"
"fmt"
"log"
"os/exec"
)

/*
*
* 树莓派文档可以参考这里:https://www.raspberrypi.com/documentation/computers/raspberry-pi.html
*
*/

const (
//-----------------------------------------------
// 注意: 该定义使用的是树莓派GPIO的【物理编号】
//-----------------------------------------------
// 4个输出
raspi_DO1 string = "11" // GPIO.0
raspi_DO2 string = "12" // GPIO.1
raspi_DO3 string = "13" // GPIO.2
raspi_DO4 string = "15" // GPIO.3

// 4个输入
raspi_DI1 string = "16" // GPIO.4
raspi_DI2 string = "18" // GPIO.5
raspi_DI3 string = "22" // GPIO.6
raspi_DI4 string = "29" // GPIO.21
)

const (
raspi_Out string = "out"
raspi_In string = "in"
)

func init() {
_RASPI4B_GPIOAllInit()
}
func _RASPI4B_GPIOAllInit() {
// 初始化输入
_RASPI4B_GPIOInit(raspi_DO1, raspi_Out)
_RASPI4B_GPIOInit(raspi_DO2, raspi_Out)
_RASPI4B_GPIOInit(raspi_DO3, raspi_Out)
_RASPI4B_GPIOInit(raspi_DO4, raspi_Out)
// 初始化输出
_RASPI4B_GPIOInit(raspi_DI1, raspi_In)
_RASPI4B_GPIOInit(raspi_DI2, raspi_In)
_RASPI4B_GPIOInit(raspi_DI3, raspi_In)
_RASPI4B_GPIOInit(raspi_DI4, raspi_In)
}

func _RASPI4B_GPIOInit(Pin string, EnDir string) {
//gpio export
cmd := fmt.Sprintf("echo %s > /sys/class/gpio/export", Pin)
_, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
log.Println(err)
}
// gpio set direction
cmd = fmt.Sprintf("echo %s > /sys/class/gpio/gpio%s/direction", EnDir, Pin)
_, err = exec.Command("sh", "-c", cmd).Output()
if err != nil {
log.Println(err)
}
}

func RASPI4_GPIOSet(pin, value int) (bool, error) {
cmd := fmt.Sprintf("echo %d > /sys/class/gpio/gpio%d/value", value, pin)
_, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
log.Println(err)
}
v, e := RASPI4_GPIOGet(pin)
if e != nil {
return false, e
}
return v == value, nil
}

func RASPI4_GPIOGet(pin int) (int, error) {
cmd := fmt.Sprintf("cat /sys/class/gpio/gpio%d/value", pin)
Value, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
return -1, err
}
if len(Value) < 1 {
return -1, errors.New("invalid length")
}
if Value[0] == '0' {
return 0, nil
}
if Value[0] == '1' {
return 1, nil
}
return -1, errors.New("invalid value")
}
14 changes: 14 additions & 0 deletions archsupport/raspberry4b_adda_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package archsupport

/*
*
* Windows下我们不实现 但是留下接口防止未来扩展的时候改代码
*
*/

func RASPI4_GPIOSet(pin, value int) (bool, error) {
return false, nil
}
func RASPI4_GPIOGet(pin int) (int, error) {
return 0, nil
}
21 changes: 20 additions & 1 deletion archsupport/readme.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,21 @@
# 跨平台
如果有不同操作系统上的实现库,建议统一放置此处。可参考下面的hello文件里面的程序。
这里放置一些对特定硬件的支持库,一般指的是定制化网关产品。如果有不同操作系统上的实现库,建议统一放置此处。可参考下面的hello文件里面的程序。

## 当前兼容
### EEKIT 网关
EEKIT 是 RULEX 团队的默认硬件,操作系统为`64位OpenWrt、Armbian`, CPU 架构为`64位全志H3`。EEKIT 网关的lua标准库命名空间为`eekit`
### 树莓派4B+
除此之外,还对`树莓派4B`的 GPIO 做了支持。树莓派的lua标准库命名空间为`raspberry`

## 环境变量
如果要启用硬件特性,需要在启动的时候加入 `ARCHSUPPORT` 环境变量来指定运行的版本, 例如要在 EEKIT-H3网关上运行:
```sh
ARCHSUPPORT=EEKITH3 rulex run
```
## 支持硬件列表
| 硬件名 | 环境参数 | 示例 |
| --------------- | -------- | ------------------------------- |
| EEKITH3版本网关 | EEKITH3 | `ARCHSUPPORT=EEKITH3 rulex run` |
| 树树莓派4B、4B+ | RPI4 | `ARCHSUPPORT=RPI4B rulex run` |

> 警告: 默认为 EEKITH3, 如果你自己需要定制,最好针对自己的硬件进行跨平台适配, 如果没有指定平台,可能会导致预料之外的结果。
4 changes: 4 additions & 0 deletions engine/lua_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,12 @@ func LoadBuildInLuaLib(e typex.RuleX, r *typex.Rule) {
//------------------------------------------------------------------------
// 注册GPIO操作函数到LUA运行时
//------------------------------------------------------------------------
// EEKIT
r.AddLib(e, "eekit", "GPIOGet", rulexlib.EEKIT_GPIOGet(e))
r.AddLib(e, "eekit", "GPIOSet", rulexlib.EEKIT_GPIOSet(e))
// 树莓派4B
r.AddLib(e, "raspi4b", "GPIOGet", rulexlib.RASPI4_GPIOGet(e))
r.AddLib(e, "raspi4b", "GPIOSet", rulexlib.RASPI4_GPIOSet(e))

}

Expand Down
2 changes: 1 addition & 1 deletion plugin/http_server/appstack_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ AppDESCRIPTION = "%s"
`
const defaultLuaMain = `
function Main(arg)
print("Hello World")
print("Hello World:", applib:Time())
return 0
end
`
Expand Down
46 changes: 46 additions & 0 deletions rulexlib/raspberry4b_adda_lib.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package rulexlib

import (
"github.com/i4de/rulex/typex"
"github.com/i4de/rulex/vendor3rd"
lua "github.com/yuin/gopher-lua"
)

/*
*
* 读GPIO, lua的函数调用应该是这样: eekit:GPIOGet(pin) -> v,error
*
*/
func RASPI4_GPIOGet(rx typex.RuleX) func(*lua.LState) int {
return func(l *lua.LState) int {
pin := l.ToNumber(2)
v, e := vendor3rd.RASPI4_GPIOGet(int(pin))
if e != nil {
l.Push(lua.LNil)
l.Push(lua.LString(e.Error()))
} else {
l.Push(lua.LNumber(v))
l.Push(lua.LNil)
}
return 2
}
}

/*
*
* 写GPIO, lua的函数调用应该是这样: eekit:GPIOSet(pin, v) -> error
*
*/
func RASPI4_GPIOSet(rx typex.RuleX) func(*lua.LState) int {
return func(l *lua.LState) int {
pin := l.ToNumber(2)
value := l.ToNumber(3)
_, e := vendor3rd.RASPI4_GPIOSet(int(pin), int(value))
if e != nil {
l.Push(lua.LString(e.Error()))
} else {
l.Push(lua.LNil)
}
return 1
}
}
8 changes: 4 additions & 4 deletions test/appstack_httpapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func Test_CURD_App(t *testing.T) {
}
func UT_createApp(t *testing.T) string {
// 通过接口创建一个App
body := `{"name": "hello_world","version": "1.0.0","autoStart": true,"description": "hello world"}`
body := `{"name": "testlua1","version": "1.0.0","autoStart": true,"description": "hello world"}`
output, err := exec.Command("curl",
"-X", "POST", "http://127.0.0.1:2580/api/v1/app",
"-H", "Content-Type: application/json", "-d", body).Output()
Expand All @@ -44,7 +44,7 @@ func UT_createApp(t *testing.T) string {
unitTestDB.Raw("SELECT * FROM m_apps").Find(&mApp)
assert.Equal(t, 1, len(mApp))
t.Log(mApp[0].UUID)
assert.Equal(t, mApp[0].Name, "hello_world")
assert.Equal(t, mApp[0].Name, "testlua1")
assert.Equal(t, mApp[0].Version, "1.0.0")
assert.Equal(t, mApp[0].AutoStart, true)
return mApp[0].UUID
Expand All @@ -55,7 +55,7 @@ func UT_createApp(t *testing.T) string {
*
*/
func UT_updateApp(t *testing.T, uuid string) {
body := `{"uuid": "%s","name": "hello_world1","version": "1.0.1","autoStart": false,"luaSource":"AppNAME='OK1'\nAppVERSION='0.0.3'\nfunction Main()\n\tprint('Hello-World')\nend"}`
body := `{"uuid": "%s","name": "testlua11","version": "1.0.1","autoStart": false,"luaSource":"AppNAME='OK1'\nAppVERSION='0.0.3'\nfunction Main()\n\tprint('Hello-World')\nend"}`
t.Logf(body, uuid)
output, err := exec.Command("curl",
"-X", "PUT", "http://127.0.0.1:2580/api/v1/app",
Expand All @@ -69,7 +69,7 @@ func UT_updateApp(t *testing.T, uuid string) {
unitTestDB.Raw("SELECT * FROM m_apps").Find(&mApp)
assert.Equal(t, 1, len(mApp))
t.Log(mApp[0].UUID)
assert.Equal(t, mApp[0].Name, "hello_world1")
assert.Equal(t, mApp[0].Name, "testlua11")
assert.Equal(t, mApp[0].Version, "1.0.1")
assert.Equal(t, mApp[0].AutoStart, false)
}
Expand Down
6 changes: 3 additions & 3 deletions typex/version.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//
// Warning:
// This file is generated by go compiler, don't change it!!!
// Generated Time: "2023-03-08 17:54:02"
// Build on: 5.18.17-amd64-desktop-community-hwe
// Generated Time: "2023-03-08 23:47:20"
// Build on: 5.15.90.1-microsoft-standard-WSL2
//
package typex

Expand All @@ -13,6 +13,6 @@ type Version struct {

var DefaultVersion = Version{
Version: `v0.4.3`,
ReleaseTime: "2023-03-08 17:54:02",
ReleaseTime: "2023-03-08 23:47:20",
}

6 changes: 3 additions & 3 deletions typex/xappstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ func (app *Application) Stop() {
log.Println("[gopher-lua] app stop:", app.UUID, ", with recover error: ", err)
}
}()
app.vm.DoString(`function __1() end __1()`)
app.vm.Pop(0)
app.vm.DoString(`function __() end __()`)
app.vm.SetTop(0)
app.cancel()
// app.vm.Close()
// app.vm.Close() // app.vm.Close 会导致panic, 但是本次用了巧妙的手段来实现结束进程
}

/*
Expand Down
2 changes: 1 addition & 1 deletion utils/banner.b
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
|
|* Welcome to RULEX framework world <'_'>
|* Version: v0.4.3-d5df539dbd1a97d
|* Build at: 2023-03-08 17:54:02
|* Build at: 2023-03-08 23:47:20
|* Document: https://rulex.pages.dev
|
18 changes: 18 additions & 0 deletions vendor3rd/raspberry4b_adda_support.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package vendor3rd

import (
"github.com/i4de/rulex/archsupport"
)

/*
*
* 跨平台支持
*
*/

func RASPI4_GPIOSet(pin, value int) (bool, error) {
return archsupport.RASPI4_GPIOSet(pin, value)
}
func RASPI4_GPIOGet(pin int) (int, error) {
return archsupport.RASPI4_GPIOGet(pin)
}

0 comments on commit 6e2fffa

Please sign in to comment.