Hi,

> -----Original Message-----
> From: openwrt-devel [mailto:[email protected]]
> On Behalf Of Bjørn Mork
> Sent: Dienstag, 9. März 2021 22:18
> To: [email protected]
> Cc: John Crispin <[email protected]>; Bjørn Mork <[email protected]>
> Subject: [PATCH] rtl83xx-poe: add package
> 
> From: John Crispin <[email protected]>
> 
> Signed-off-by: John Crispin <[email protected]>
> Signed-off-by: Bjørn Mork <[email protected]>

This lacks a commit message.

Is this needed in core repo?

A few nitpicks below.

> ---
> This is John's simple PoE daemon for the realtek devices, which has been
> cycling around in assorted repos since last year.  It's well tested by now.  
> I've
> been running this with constant polling from cacti for a few months now
> without any issues.
> 
> I believe this should be included in master to make it easier to find and 
> install
> for new users.
> 
> 
> 
> Bjørn
> 
> 
>  package/rtl83xx-poe/Makefile             |  29 +++
>  package/rtl83xx-poe/files/bin/poe.lua    | 316 +++++++++++++++++++++++
>  package/rtl83xx-poe/files/etc/config/poe |  10 +  package/rtl83xx-
> poe/files/etc/init.d/poe |  18 ++
>  4 files changed, 373 insertions(+)
>  create mode 100644 package/rtl83xx-poe/Makefile  create mode 100755
> package/rtl83xx-poe/files/bin/poe.lua
>  create mode 100644 package/rtl83xx-poe/files/etc/config/poe
>  create mode 100755 package/rtl83xx-poe/files/etc/init.d/poe
> 
> diff --git a/package/rtl83xx-poe/Makefile b/package/rtl83xx-poe/Makefile
> new file mode 100644 index 000000000000..195b1eb20949
> --- /dev/null
> +++ b/package/rtl83xx-poe/Makefile
> @@ -0,0 +1,29 @@
> +include $(TOPDIR)/rules.mk
> +
> +PKG_NAME:=rtl83xx-poe
> +PKG_RELEASE:=2

Should be "1" or $(COMMITCOUNT)

> +
> +PKG_LICENSE:=GPL-2.0+

GPL-2.0-or-later

Best

Adrian


> +
> +include $(INCLUDE_DIR)/package.mk
> +
> +define Package/rtl83xx-poe
> +  SECTION:=utils
> +  CATEGORY:=Utilities
> +  DEPENDS:=+libubox-lua +libubus-lua +libuci-lua +lua-rs232
> +  TITLE:=PoE daemon for realtek switches endef
> +
> +define Package/rtl83xx-poe/description
> + This package contains an utility to allow triggering the PoE state of 
> realtek
> switch ports.
> +endef
> +
> +define Build/Compile
> +
> +endef
> +
> +define Package/rtl83xx-poe/install
> +     $(CP) ./files/* $(1)/
> +endef
> +
> +$(eval $(call BuildPackage,rtl83xx-poe))
> diff --git a/package/rtl83xx-poe/files/bin/poe.lua b/package/rtl83xx-
> poe/files/bin/poe.lua
> new file mode 100755
> index 000000000000..86dafe13cd01
> --- /dev/null
> +++ b/package/rtl83xx-poe/files/bin/poe.lua
> @@ -0,0 +1,316 @@
> +#!/usr/bin/lua
> +local rs = require "luars232"
> +
> +port_name = "/dev/ttyS1"
> +out = io.stderr
> +nseq = 0
> +
> +budget = 65.0
> +port_power = {0, 0, 0, 0, 0, 0, 0, 0 }
> +
> +if arg[1] ~= nil then
> +     budget = tonumber(arg[1])
> +end
> +for i = 1, 8 do
> +     port_power[i] = arg[i + 1]
> +end
> +
> +function initSerial(p)
> +     local e, p = rs.open(p)
> +     if e ~= rs.RS232_ERR_NOERROR then
> +             -- handle error
> +             out:write(string.format("can't open serial port '%s', error:
> '%s'\n",
> +                             port_name, rs.error_tostring(e)))
> +             return
> +     end
> +
> +     assert(p:set_baud_rate(rs.RS232_BAUD_19200) ==
> rs.RS232_ERR_NOERROR)
> +     assert(p:set_data_bits(rs.RS232_DATA_8) ==
> rs.RS232_ERR_NOERROR)
> +     assert(p:set_parity(rs.RS232_PARITY_NONE) ==
> rs.RS232_ERR_NOERROR)
> +     assert(p:set_stop_bits(rs.RS232_STOP_1) ==
> rs.RS232_ERR_NOERROR)
> +     assert(p:set_flow_control(rs.RS232_FLOW_OFF)  ==
> rs.RS232_ERR_NOERROR)
> +
> +     out:write(string.format("OK, port open with values '%s'\n",
> +tostring(p)))
> +
> +     return p
> +end
> +
> +function receive(pCon)
> +     local reply = {}
> +     local retries = 0
> +
> +     while table.getn(reply) < 12 and retries < 4 do
> +             -- Read up to 12 byte response, timeout 400ms
> +             err, data_read, size = pCon:read(12, 400)
> +             assert(err == rs.RS232_ERR_NOERROR)
> +--           io.write(string.format("-> [%2d]:", string.len(data_read)))
> +             for i = 1, string.len(data_read) do
> +                     table.insert(reply, string.byte(string.sub(data_read, i,
> i)))
> +--                   io.write(string.format(" %02x", reply[i]))
> +             end
> +--           io.write("\n")
> +             retries = retries + 1
> +     end
> +     if table.getn(reply) ~= 12 then
> +             print ("Unexpected length!")
> +             return(nil)
> +     end
> +     local sum = 0
> +     for i = 1, 11 do
> +             sum = sum + reply[i]
> +     end
> +     if sum % 256 ~= reply[12] then
> +             print ("Checksum error!")
> +             return(nil)
> +     end
> +     return(reply)
> +end
> +
> +function sendCommand(pCon, cmd)
> +     nseq = nseq + 1
> +     cmd[2] = nseq % 256
> +
> +     while table.getn(cmd) < 11 do
> +             table.insert(cmd, 0xff)
> +     end
> +     local c_string = ""
> +     local sum = 0
> +--   io.write("send  ")
> +     for i = 1, 11 do
> +             sum = sum + cmd[i]
> +--           io.write(string.format(" %02x", cmd[i]))
> +             c_string = c_string .. string.char(cmd[i])
> +     end
> +--   io.write(string.format(" %02x\n", sum % 256))
> +     c_string = c_string .. string.char(sum % 256)
> +     err, len_written = pCon:write(c_string)
> +     assert(err == rs.RS232_ERR_NOERROR)
> +
> +     local reply = receive(pCon)
> +     if reply then
> +--           io.write("recv  ")
> +--           dumpReply(reply)
> +             if (reply[1] == cmd[1] and reply[2] == cmd[2]) then
> +                     return(reply)
> +             else
> +                     if reply[1] == 0xfd then
> +                             print ("An incomplete request was received!")
> +                     elseif reply[1] == 0xfe then
> +                             print ("Request frame checksum was
> incorrect!")
> +                     elseif reply[1] == 0xff then
> +                             print ("Controller was not ready to respond !")
> +                     else
> +                             print ("Sequence number mismatch!")
> +                     end
> +             end
> +     else
> +             print ("Missing reply!")
> +     end
> +     return(nil)
> +end
> +
> +function dumpReply(reply)
> +     for i,v in ipairs(reply) do
> +             io.write(string.format(" %02x", v))
> +     end
> +     io.write("\n");
> +end
> +
> +function getStatus(pCon)
> +     local cmd = {0x20, 0x01}
> +     local reply = sendCommand(pCon, cmd)
> +     if not reply then return(nil) end
> +     -- returns status, PoEExtVersion, PoEVersion, state2
> +     return({reply[5], reply[6], reply[7], reply[10]}) end
> +
> +function disablePort(pCon, port)
> +     local cmd = {0x00, port, port, 0x00}
> +     -- disable command is always sent twice
> +     sendCommand(pCon, cmd)
> +     sendCommand(pCon, cmd)
> +end
> +
> +function enablePort(pCon, port)
> +     local cmd = {0x00, port, port, 0x01}
> +     sendCommand(pCon, cmd)
> +end
> +
> +function setPortRelPrio(pCon, port, prio)
> +     local cmd = {0x1d, 0x00, port, prio}
> +     sendCommand(pCon, cmd)
> +end
> +
> +function setGlobalPowerBudget(pCon, maxPower, guard)
> +     -- maxPower and guard Watts
> +     local cmd = {0x18, 0x01, 0x00}
> +     table.insert(cmd, math.floor(maxPower * 10 / 256))
> +     table.insert(cmd, math.floor(maxPower * 10) % 256)
> +     table.insert(cmd, math.floor(guard * 10 / 256))
> +     table.insert(cmd, math.floor(guard * 10) % 256)
> +     sendCommand(pCon, cmd)
> +end
> +
> +function setPowerLowAction(pCon, disableNext)
> +     local cmd = {0x17, 0x00}
> +     if disableNext then
> +             table.insert(cmd, 0x04)
> +     else
> +             table.insert(cmd, 0x02)
> +     end
> +     sendCommand(pCon, cmd)
> +end
> +
> +function getPowerStat(pCon)
> +     local cmd = {0x23, 0x01}
> +     local reply = sendCommand(pCon, cmd)
> +     if not reply then return(nil) end
> +     local watts = (reply[3] * 256 + reply[4]) / 10.0
> +     return watts
> +end
> +
> +function getPortPower(pCon, port)
> +     local cmd = {0x30, 0x01, port}
> +     local reply = sendCommand(pCon, cmd)
> +     if not reply then return(nil) end
> +     local watts = (reply[10] * 256 + reply[11]) / 10.0
> +     local mamps = reply[6] * 256 + reply[7]
> +     return({watts, mamps})
> +end
> +
> +function getPortOverview(pCon)
> +     local cmd = {0x2a, 0x01, 0x00}
> +     local reply = sendCommand(pCon, cmd)
> +     if not reply then return(nil) end
> +     local s = { }
> +     for i = 4, 11 do
> +             if reply[i] == 0x10 then
> +                     s[i-3] = "off"
> +             elseif reply[i] == 0x11 then
> +                     s[i-3] = "enabled"
> +             elseif reply[i] > 0x11 then
> +                     s[i-3] = "active"
> +             else
> +                     s[i-3] = "unknown"
> +             end
> +     end
> +     return(s)
> +end
> +
> +-- Priority for power: 3: High, 2: Normal, 1: Low?
> +function setPortPriority(pCon, port, prio)
> +     local cmd = {0x1a, port, port, prio}
> +     local reply = sendCommand(pCon, cmd)
> +     if not reply then return(nil) end
> +     return(unpack(reply, 4, 11))
> +end
> +
> +function getPortPowerLimits(pCon, port)
> +     local cmd = {0x26, 0x01, port}
> +     local reply = sendCommand(pCon, cmd)
> +     if not reply then return(nil) end
> +     return(reply)
> +end
> +
> +function startupPoE(pCon)
> +     local reply = nil
> +     reply = getStatus(pCon)
> +
> +     setGlobalPowerBudget(pCon, 0, 0)
> +     setPowerLowAction(pCon, nil)
> +     -- do something unknown
> +     sendCommand(pCon, {0x06, 0x00, 0x01})
> +     for i = 0, 7 do
> +             if port_power[i + 1] ~= "1" then
> +                     disablePort(pCon, i)
> +             end
> +     end
> +     -- do something unknown
> +     sendCommand(pCon, {0x02, 0x00, 0x01})
> +
> +     for i = 0, 7 do
> +             if port_power[i + 1] ~= "1" then
> +                     disablePort(pCon, i)
> +             end
> +     end
> +     -- do something unknown
> +     sendCommand(pCon, {0x02, 0x00, 0x01})
> +
> +     -- use monitor command 25
> +     sendCommand(pCon, {0x25, 0x01})
> +
> +     setGlobalPowerBudget(pCon, 65.0, 7.0)
> +     getPowerStat(pCon)
> +     -- -> 23 01 00 00 02 44 00 02 ff ff 00 6a
> +
> +     -- Set 4 unknown port properties:
> +     for i = 0, 7 do
> +             sendCommand(pCon, {0x11, i, i, 0x01})
> +             sendCommand(pCon, {0x13, i, i, 0x02})
> +             sendCommand(pCon, {0x15, i, i, 0x01})
> +             sendCommand(pCon, {0x10, i, i, 0x03})
> +     end
> +     for i = 0, 7 do
> +             if port_power[i + 1] == "1" then
> +                     enablePort(pCon, i)
> +             end
> +     end
> +
> +end
> +
> +local p = initSerial(port_name)
> +startupPoE(p)
> +
> +require "ubus"
> +require "uloop"
> +
> +uloop.init()
> +
> +local conn = ubus.connect()
> +if not conn then
> +        error("Failed to connect to ubus") end
> +
> +local my_method = {
> +     poe = {
> +             info = {
> +                     function(req, msg)
> +                             local reply = {}
> +
> +                             reply.power_consumption =
> tostring(getPowerStat(p)).."W"
> +                             reply.power_budget = tostring(budget).."W"
> +
> +                             reply.ports = {}
> +                             local s = getPortOverview(p)
> +                             for i = 1, 8 do
> +                                     if s[i] == "active" then
> +                                             local r = getPortPower(p, i - 1)
> +                                             reply.ports[i] =
> tostring(r[1]).."W"
> +                                     else
> +                                             reply.ports[i] = s[i]
> +                                     end
> +                             end
> +                             conn:reply(req, reply);
> +                     end, {}
> +             },
> +             port = {
> +                     function(req, msg)
> +                             local reply = {}
> +                             if msg.port < 1 or msg.port > 8 then
> +                                     conn:reply(req, false);
> +                                     return -1
> +                             end
> +                             if msg.enable == true then
> +                                     enablePort(p, msg.port - 1)
> +                             else
> +                                     disablePort(p, msg.port - 1)
> +                             end
> +                             conn:reply(req, reply);
> +                     end, {port = ubus.INT32, enable = ubus.BOOLEAN }
> +             },
> +     },
> +}
> +
> +conn:add(my_method)
> +
> +uloop.run()
> diff --git a/package/rtl83xx-poe/files/etc/config/poe b/package/rtl83xx-
> poe/files/etc/config/poe
> new file mode 100644
> index 000000000000..4fc9723c88c7
> --- /dev/null
> +++ b/package/rtl83xx-poe/files/etc/config/poe
> @@ -0,0 +1,10 @@
> +config poe poe
> +     option budget   65
> +     option port1    0
> +     option port2    0
> +     option port3    0
> +     option port4    0
> +     option port5    0
> +     option port6    0
> +     option port7    0
> +     option port8    0
> diff --git a/package/rtl83xx-poe/files/etc/init.d/poe b/package/rtl83xx-
> poe/files/etc/init.d/poe
> new file mode 100755
> index 000000000000..159340b03a38
> --- /dev/null
> +++ b/package/rtl83xx-poe/files/etc/init.d/poe
> @@ -0,0 +1,18 @@
> +#!/bin/sh /etc/rc.common
> +START=40
> +
> +USE_PROCD=1
> +PROG=/bin/poe.lua
> +
> +start_service() {
> +     local budget=$(uci get poe.poe.budget)
> +
> +     procd_open_instance
> +     procd_set_param command "$PROG"
> +     procd_append_param command ${budget:-65}
> +     for p in `seq 1 8`; do
> +             local pwr=$(uci get poe.poe.port$p)
> +             procd_append_param command  ${pwr:-0}
> +     done
> +     procd_close_instance
> +}
> --
> 2.20.1
> 
> 
> _______________________________________________
> openwrt-devel mailing list
> [email protected]
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Attachment: openpgp-digital-signature.asc
Description: PGP signature

_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to