自定义openwrt的配置界面:luci进阶之路

2023-10-27

5. 20 晴 今天的太阳挺大的,晒得我进园区直接37. 3警告,于是我百度搜索微信朋友圈怎么关闭,才把温度稳定下来。算了算了,上班说事

由于公司部门调动,逐渐接触到新的知识,新的模块;还听说这玩意比较冷门,没办法,该搞还是得搞,又不是搞不了,下面就最近一个多月的研究写点东西,废话不多说,实操起来。

一、LUCI的MVC

要实现一个简单的自定义web界面,完成基本的配置需求,其实只需要用到控制层+model层的业务代码,view层的htm暂时可放一边。

  1. 知识背景,预备工作
    先看看新安装的openwrt软路由界面,
    下图所示版本的软路由下载地址是:http://firmware.koolshare.cn/LEDE_X64_fw867/
    具体的安装配置可以参考:
    https://blog.csdn.net/qq_41953807/article/details/106118556
    搭建好后,访问web界面得到如下图
    在这里插入图片描述
    这款固件的web主题有三种,上述是默认的,菜单栏在左侧,修改主题可按上图1->2->3->4进行设置,保存并应用。
  2. 需求说明
    现在需要在原有的菜单上新增一块栏目,并设置菜单项,每个菜单项具有自己的配置,并实现web与固件的读写操作。下面开始代码部分
  3. 进入openwrt的命令行
    openwrt其实就是小型的Linux,具备Linux常用的操作命令,luci安装的目录在 /usr/lib/lua/luci
    在这里插入图片描述
  4. controller控制层
    cd 进入controller/admin目录,在此处新建一个terminal.lua文件(vi命令和touch命令均可)
    文件内容如下:
--terminal.lua
module("luci.controller.admin.terminal",package.seeall)

function index()
	local page=node('admin','terminal')
	page.target=firstchild()
	page.title=_('终端采集系统')
	page.order=70
	page.index=true

	entry({"admin","terminal"},alias("admin","terminal","site-manager"),_("终端采集系统"),50).index=true
	entry({"admin","terminal","site-manager"},cbi("admin_terminal/site-manager"),_("站点管理"),1)
	entry({"admin","terminal","args-modify"},cbi("admin_terminal/args-modify"),_("参数修改"),2)

	entry({"admin","terminal","set"},cbi("admin_terminal/addtest"),_("Set"),3)
	entry({"admin","terminal","addtest"},call("action_info"),_("Info"),4)
	entry({"admin","terminal","testnixio"},template("test_nixio"),_("test nixio"),5)	
end

function action_info()
	if not nixio.fs.access("/tmp/addtest") then
		return
	end

	local info = nixio.fs.readfile("/tmp/addtest")
	luci.template.render("addtest_info",{info=info})
end

简略说明:page节点是挂在菜单栏上,新建一个自定义菜单用的。
entry是菜单项,其他的资料比较齐全,可自行查阅。

  1. model模型层的cbi
    正如控制层entry指出的目录,进入model/cbi目录下,有样学样,新建admin_terminal目录,进入并新建args-modify.lua 和 site-manager.lua等文件
    在这里插入图片描述
    site-manager.lua 内容如下
--site-manager.lua 
require("luci.sys")

m=Map("site-manager",translate("站点管理"),translate("终端采集系统的站点管理部分配置"))
m:chain("luci")

s=m:section(TypedSection,"site","配置SectionType为site,在/etc/config/site-manager中的test")
s.addremove=false
s.anonymous=true

s:option(Value,"site_id",translate("站点编号:"))
s:option(Value,"site_name",translate("站点名称:"))
s:option(Value,"site_addr",translate("地址:"))
s:option(Value,"site_longitude",translate("经度:"))
s:option(Value,"site_latitude",translate("纬度:"))
s:option(Value,"create_time",translate("创建日期:"))
s:option(Value,"device_addr",translate("设备地址:"))
s:option(Value,"subnet_mask",translate("子网掩码:"))
s:option(Value,"gateway",translate("网关:"))
s:option(Value,"server_addr",translate("服务器地址:"))
s:option(Value,"server_bak_addr",translate("备用服务器地址:"))
s:option(TextValue,"note",translate("备注:"))


return m

args-modify.lua 内容如下

--args-modify.lua 
require("luci.sys")

m=Map("site-manager",translate("参数修改"),translate("终端采集系统的参数修改部分配置"))
--m:chain("luci")
local input_device_id="RWL1501023A140F10088"

b=m:section(TypedSection,"args","设备编号:"..input_device_id)
b.addremove=false
b.anonymous=true
--tag1=b:option(DummyValue,"pci","PCI1")
--b:option(Value,"work_freq_point",translate("hh"))
local str1=string.sub(input_device_id,8,9)
local str2=string.sub(input_device_id,10,10)
local str3=string.sub(input_device_id,11,11)
local num1=tonumber(str1,16)
local num2=tonumber(str2,16)
local num3=tonumber(str3,16)


local function band1()
	b:tab("tab1","Band1(FDD)")
	f1=b:taboption("tab1",Flag,"radio_freq_enable","射频开关")
	v1=b:taboption("tab1",Value,"work_freq_point","工作频点")
	v2=b:taboption("tab1",Value,"cell_band_width","小区带宽")
	v3=b:taboption("tab1",Value,"pci","PCI")
	v4=b:taboption("tab1",Value,"tac","TAC")
	v5=b:taboption("tab1",Value,"cell_id","Cell ID")
	v6=b:taboption("tab1",Value,"transmitting_power","发射功率")
	v7=b:taboption("tab1",Value,"is_recapture","是否重新捕获")
	v8=b:taboption("tab1",Value,"capture_time","重捕获时间(秒)")
	v9=b:taboption("tab1",Value,"plmn","PLMN")
	v10=b:taboption("tab1",Value,"is_redirect","是否重定向")
	v11=b:taboption("tab1",Value,"redirect_type","重定向制式")
	v12=b:taboption("tab1",Value,"tdd_sync_way","TDD同步方式")
	v13=b:taboption("tab1",Value,"frame_head_offset","帧头偏移值")
	f2=b:taboption("tab1",Flag,"auto_open_cell","开机自动开小区")
	b1=b:taboption("tab1",Button,"btn_reboot","设备重启")
	b1.inputtitle=translate("别点")
	b1.inputstyle="apply"	
end
local function band3()
	b:tab("tab3","Band3(FDD)")
	b:taboption("tab3",Flag,"enable","开关")
end
local function band5()
	b:tab("tab5","Band5(FDD)")
	b:taboption("tab5",Flag,"enable","开关")
end
local function band8()
	b:tab("tab8","Band8(FDD)")
	b:taboption("tab8",Flag,"enable","开关")
end
local function band34()
	b:tab("tab34","Band34(TDD)")
	b:taboption("tab34",Flag,"enable","开关")
end
local function band38()
	b:tab("tab38","Band38(TDD)")
	b:taboption("tab38",Flag,"enable","开关")
end
local function band39()
	b:tab("tab39","Band39(TDD)")
	b:taboption("tab39",Flag,"enable","开关")
end
local function band40()
	b:tab("tab40","Band40(TDD)")
	b:taboption("tab40",Flag,"enable","开关")
end
local function two2g()
	b:tab("tab2g","2G")
	b:taboption("tab2g",Flag,"enable","开关")
end
local function wifi()
	b:tab("tabwifi","WI-FI")
	b:taboption("tabwifi",Flag,"enable","开关")
end

if(num2==1) then
	band1()
elseif(num2==2) then
	band3()
elseif(num2==3) then
	band1()
	band3()
elseif(num2==4) then
	band5()
elseif(num2==5) then
	band1()
	band5()
elseif(num2==6) then
	band3()
	band5()
elseif(num2==7) then
	band1()
	band3()
	band5()
elseif(num2==8) then
	band8()
elseif(num2==9) then
	band1()
	band8()
elseif(num2==10) then
	band3()
	band8()
elseif(num2==11) then
	band1()
	band3()
	band8()
elseif(num2==12) then
	band5()
	band8()
elseif(num2==13) then
	band1()
	band5()
	band8()
elseif(num2==14) then
	band3()
	band5()
	band8()
elseif(num2==15) then
	band1()
	band3()
	band5()
	band8()
end

if(num3==1) then
	band34()
elseif(num3==2) then
	band38()
elseif(num3==3) then
	band34()
	band38()
elseif(num3==4) then
	band39()
elseif(num3==5) then
	band34()
	band39()
elseif(num3==6) then
	band38()
	band39()
elseif(num3==7) then
	band34()
	band38()
	band39()
elseif(num3==8) then
	band40()
elseif(num3==9) then
	band34()
	band40()
elseif(num3==10) then
	band38()
	band40()
elseif(num3==11) then
	band34()
	band38()
	band40()
elseif(num3==12) then
	band39()
	band40()
elseif(num3==13) then
	band34()
	band39()
	band40()
elseif(num3==14) then
	band38()
	band39()
	band40()
elseif(num3==15) then
	band34()
	band38()
	band39()
	band40()
end

if(num1==1) then
	two2g()
elseif(num1==2) then
	wifi()
elseif(num1==3) then
	two2g()
	wifi()
end

--设备重启按钮
if b1 then
	local reboot = luci.http.formvalue("cbid.site-manager.test2.btn_reboot")
	if reboot=="别点" then
	b:option(DummyValue,"tuichu","重启中")
	luci.sys.exec("/etc/init.d/uhttpd restart")
	end
end

--保存并应用按钮
local apply = luci.http.formvalue("cbi.apply")
if apply then
	luci.sys.exec("uci commit terminal")
end

--页面跳转示例
--local myurl=luci.dispatcher.build_url("admin/terminal/site-manager")
--luci.http.write("<script>location.href='"..myurl.."';</script>")

return m

addtest.lua内容

--addtest.lua 
m=Map("addtest",translate("Luci practice"),translate("fager's test"))

s=m:section(TypedSection,"arguments","")
s.addremove=true
s.anonymous=false

s:option(Flag,"enable",translate("Enable"))
s:option(Value,"interval",translate("Interval"))
s:option(Value,"content",translate("Content"))

local apply=luci.http.formvalue("cbi.apply")
if apply then
	--luci.sys.exec("/etc/init.d/addtestd start")
end

return m

  1. 该去写配置文件了
    根据model层的代码,在创建Map的时候,第一个参数指定了配置文件的名称,而该配置文件的目录在/etc/config/下面
    site-manager文件内容,这里可以用UCI命令进行操作,也可以vi,UCI命令资料挺多,自行查阅。

config site 'test'
	option site_id '001'
	option site_name '站点1'
	option site_addr 'beijing'
	option site_longitude '24.5'
	option site_latitude '34.8'
	option create_time '2020-04-24 15:41:20'
	option device_addr '192.168.12.25'
	option subnet_mask '255.255.0.0'
	option gateway '192.168.12.1'
	option server_addr '192.168.12.125'
	option server_bak_addr '192.168.13.125'
	option note '哈哈哈, 我改了'

config args 'test2'
	option work_freq_point '375'
	option radio_freq_enable '1'
	option cell_band_width '5M'
	option pci '123'
	option tac '11'
	option cell_id '002'
	option transmitting_power '10W'
	option is_recapture '是'
	option plmn '46000'
	option capture_time '1800'
	option is_redirect '否'
	option redirect_type 'oo'
	option tdd_sync_way 'GPS/空口'
	option frame_head_offset '0'
	option auto_open_cell '1'
	option aa '设备重启'
	option btn_reboot '别点'

addtest 内容


config arguments
	option enable '1'
	option interval '2'
	option content '555566'
  1. 看看页面效果
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这下或许有的朋友来疑问了,最后一张图咋肥事,没有啊。回头看一下控制层的代码,其中一行是
	entry({"admin","terminal","testnixio"},template("test_nixio"),_("test nixio"),5)	

template,访问view层下面的.htm文件,所以最后还是走向了页面,下面来说说socket通讯与view。

  1. openwrt的socket通讯
    在/usr/lib/lua目录下,我们还能看到nixio目录,查看我的另一篇博客
    https://blog.csdn.net/qq_41953807/article/details/106146353大致知道是通过nixio.socket通讯,关于nixio的api可以参考
    https://blog.csdn.net/qq_41953807/article/details/106131591
    在这里插入图片描述

通过上述entry指定文件test_nixio.htm ,内容如下

<%+header%>

<%
	local h=require "luci.http"
	local c=require "luci.resttemplate"
	

--	h.write("Hello World</br>")
--	h.write("测试socket通信失败!<Br>")
--	h.write(c.send("luci web's page Client!"))

	h.write(c.send(""))

	
%>
<%+footer%>

说明:lua是脚本语言,可在htm文件内直接使用<%%>进行引用。
阅读代码,其中luci.http是在/usr/lib/lua/luci目录下安装自带的http.lua文件;luci.resttemplate是我自定义的根据nixio编写的socket通讯简单工具类,能访问远程的服务,调用远程的接口!
同理,在/usr/lib/lua/luci目录下创建resttemplate.lua文件,内容如下:

--resttemplate.lua 
core={}

local h=require "luci.http"
local n=require "nixio"

core.ip="192.168.80.192"
core.port=8080
core.uri="/users"
core.method="GET"
core.charset="UTF-8"
core.rcvTimeout=20

function core.get(name)

end

function core.httpData(data)
--	core.uri=string.upper(core.uri)
	core.uri="/users"
	return core.method.." "..core.uri.." HTTP/1.1\r\n"..
		"Host: "..core.ip..":"..core.port.."\r\n"..
		"Content-type: text/html;charset="..core.charset.."\r\n"..
		"Accept-Language: zh-cn\r\n"..
		"User-Agent: Mozilla/4.0(Compatible win32; MSIE)\r\n"..
		"Content-Length: "..string.len(data).."\r\n"..	
		"Connection: close\r\n\r\n"..
		data
end

function core.restData(method,uri,data,ip,port)
	data=data or ""
	method=method or "GET"
	uri=uri or "/"
	return method.." "..uri.." HTTP/1.1\r\n"..
		"Accept: */*\r\n"..
		"Accept-Encoding: gzip, deflate, br\r\n"..
		"Accept-Language: zh-CN,zh;q=0.9\r\n"..
		"Connection: keep-alive\r\n"..
		"Host: "..ip..":"..port.."\r\n"..
		"Content-Length: "..string.len(data).."\r\n"..
		data
end

function core.testget(data)
		
	socket:setopt("socket","rcvtimeo",timeout)
	socket:send(core.httpData(data))
	local tt={}
	repeat
		local tmp=socket:recv(100)
		if tmp==false then
			socket:close()
			return false,"response timeout"
		end
		
		tmp=tostring(tmp)
		local i= #tt
		tt[i+1]=tmp
	until #tmp < 1
	
	socket:close()

	return true,"success 200"
end

function core.send(data)
	local position
	local t={}
	local http
	local socket=nixio.socket("inet","stream")
	local tmp

	if not socket then
		return false, "创建socket失败"
	end

	if not socket:connect(core.ip,core.port) then
		socket:close()
		return false, "服务无响应,连接服务器"..core.ip..":"..core.port.."失败"
	end

	socket:setopt("socket","rcvtimeo",core.rcvTimeout)

	socket:send(core.httpData(data))

	repeat
		tmp=socket:recv(100)
	
		if tmp==false then
			socket:close()
			return false,"响应超时"
		end
		tmp=tostring(tmp)
		t[#t + 1] = tmp
	until #tmp < 1

	socket:close()
	
	local result=table.concat(t)
	
	position=string.find(result,"\r\n\r\n")

	if position==nil then
		return false,"返回的数据格式不合法。数据:"..result
	end

	result=string.sub(result,string.find(result,"\r\n\r\n")+4)

	return result
end

--create a socket with ip,port,timeout
function core.socket(ip,port,timeout)
	local socket=nixio.socket("inet","stream")
	if not socket then
		return false,"create socket('inet','stream') failed!"
	end
	if not socket:connect(ip,port) then
		socket:close()
		return false,"connect "..ip..":"..port.." failed!"
	end
	socket:setopt("socket","rcvtimeo",timeout)
	return socket
end

function core.post()

end

return core

说明:此处参考了大佬的代码,
https://www.cnblogs.com/AUOONG/archive/2012/04/16/2451485.html
并根据自己对nixio和luci的相关api的理解,稍加改进,进行了一些验证。

  1. 验证

在本地IDEA上用tomcat启动了一个java编写的程序
在这里插入图片描述
就拿其中的最后一个GET请求作示例吧;
在这里插入图片描述
通过swagger点击测试,我们看到有返回数据的。
那现在不通过swagger页面点击,而是通过自己刚刚编写的test_nixio.htm页面进行访问,调用该接口试试:

点击test nixio,页面响应如下
在这里插入图片描述
可以看到页面也显示了响应的结果,完成了通讯。
但是多了69和0这两个数字。咋肥事呢?
下回分解:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义openwrt的配置界面:luci进阶之路 的相关文章

  • Lua 如何创建可用于变量的自定义函数?

    对于像 io close 这样的方法 你可以像这样使用它 file close 有没有办法创建一个像这样工作的自定义函数 您可以在变量上调用它 对我来说 我尝试使用它通过使用 string find 查找空格来将参数与文本文件分开 所以在文
  • 为什么 LuaJIT 和 Lua 中的数字舍入格式不同?

    Using string format 据说遵循 Csprintf 在 LuaJIT 轮次中格式化数字与我尝试过的所有其他 Lua 解释器不同 lua v Lua 5 4 1 Copyright C 1994 2020 Lua org PU
  • Kong - 验证上游 ssl(ssl_proxy 打开)

    我已经成功为 API 安装了 kong 网关 该 API 通过上游负载平衡到多个目标 应用程序服务器 现在 我有一个我的应用程序服务器的自签名证书 kong 和目标之间的 ssl 握手应该失败 我推断 kong 不验证上游证书 经过一些研究
  • 尝试将 nil 与数字堆栈回溯进行比较?

    我正在通过以下链接玩 Lua https www lua org pil 4 2 html https www lua org pil 4 2 html并对某一点感到困惑 Lua 5 2 4 Copyright C 1994 2015 Lu
  • Lua中如何获取表中的最大整数?

    Lua中如何获取表中的最大整数 在Lua 5 1及更早版本中 你可以使用 math max unpack 1 2 3 4 5 这受到Lua堆栈大小的限制 在 PUC Lua 5 1 上 该值的最大值可达 ca 8000 个数字 如果堆栈空闲
  • 为什么 LuaJIT 这么好?

    编辑 不幸的是 LuaJIT 已从下面链接的比较中删除 This 比较 http shootout alioth debian org u64 which programming languages are fastest php编程语言的
  • 在lua中组合两个函数

    我刚开始学习lua 所以我的要求可能是不可能的 现在 我有一个接受函数的方法 function adjust focused window fn local win window focusedwindow local winframe w
  • 如何使用 srlua 制作可执行的 Lua 脚本?

    我的主要目标是使我的 lua 文件成为可执行文件或使其成为咬代码 最好是两者皆有 我正在尝试 srlua 但在自述文件中它告诉我要做的事情 对于Windows 您需要首先创建srlua exe和glue exe 然后为每个 你想把Lua程序
  • 在Luasocket中,在什么条件下,即使在select告诉它可以安全读取之后,accept调用也可以阻塞?

    卢阿索基特select http w3 impa br diego software luasocket socket html select函数应该告诉何时可以在不阻塞的情况下读取套接字 它显然也可以用来告诉服务器套接字何时准备好接受新连
  • 关闭 Löve2D 中的抗锯齿功能

    我在用着L ve2D http love2d org用于编写一个小游戏 L ve2D 是 Lua 的开源游戏引擎 我遇到的问题是 当您在非整数位置绘制精灵时 某些抗锯齿过滤器会自动应用于精灵 love graphics draw sprit
  • 在 Awesome-wm 中为特定应用程序设置窗口布局

    如何配置很棒 以便它可以启动两个窗口对齐的新应用程序 如下所示 xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx 其中 x 是 pidgin 中的对话窗口 是好友列表窗口 一般来说 我想指定右窗口的宽度
  • 如何从 Lua 内部运行另一个脚本?

    我需要从另一个 Lua 脚本中执行一个 Lua 脚本 有多少种方法 我该如何使用它们 通常您会使用以下内容 dofile filename lua 但你可以通过以下方式做到这一点require 很好 例子 foo lua io write
  • 克隆一个lua状态

    最近 我在使用C 和Lua进行开发时遇到了很多困难 我的情况是 由于某种原因 我的 C 程序中可能有数千个 Lua 状态 但这些状态在初始化后应该是相同的 当然 我可以为每个状态执行 luaL loadlibs 和 lua loadfile
  • 如何从表成员中引用lua表成员?

    我在 lua 有一张表 enUS LOCALE STHOUSANDS Thousands separator e g comma patNumber d LOCALE STHOUSANDS d regex to find a number
  • 在 Lua/LuaFileSystem 中创建一个新文件

    我已经查看了 Lua 和 LuaFileSystem 文档 但尚未找到创建新文件的方法 我也在这里四处寻找 但目的相同 请注意 我正在寻找的解决方案必须与操作系统无关 以确保可移植性 但我很高兴针对不同的系统获得不同的答案 示例 将 Hel
  • 将值存储在 lua 的 userdata 对象中

    我想做的是这样的 object foo bar print object foo 其中 对象 是用户数据 我已经用谷歌搜索了一段时间 使用关键字 newindex 和 lua rawset 但我找不到任何可以实现我想要的功能的示例 我想用
  • 如何使用 Torch7 进行预测

    我仍在熟悉 Torch 到目前为止一切顺利 然而 我遇到了一个死胡同 我不知道如何解决 如何让 Torch7 或更具体地说 dp 库 来评估单个输入并返回预测输出 这是我的设置 基本上是 dp 演示 require dp hyperpara
  • luajit2.0.0 -- 分段错误:11

    我使用一个简单的例子http lua users org wiki SimpleLuaApiExample http lua users org wiki SimpleLuaApiExample进行测试 该示例可以成功静态链接libluaj
  • 构建自动化和 MySQL Workbench 脚本:正向工程师 SQL CREATE SCRIPT

    我目前正在研究自动化软件构建过程 其中包括 MySQL Workbench 中定义的数据库架构 使用 Workbench 的脚本编写功能 我想打开一个 Workbench 文档并将其架构导出为 SQL CREATE 脚本 我想知道是否有一个
  • 在 Lua 中更改元表会破坏冒号运算符

    在学习Lua的过程中 我借用了一些代码here http lua users org wiki StringIndexing使用字符串索引 正是这样 getmetatable index function str i return stri

随机推荐

  • Qt添加资源文件编译出错

    编译显示错误 no rule to make target needed by 发现添加的资源文件中有中文命名的 将之改成英文 错误解决
  • rabbitmq基础4——单机多节点集群、多机集群部署、基础功能测试

    文章目录 一 一机多实例集群 1 1 三机启动 1 2 立主纳从 1 3 查看集群状态 1 4 web监控 1 5 测试 1 5 1 数据同步 1 5 2 一从死 主仍战 1 5 3 从复活 死亡期间数据同步 1 5 4 主死 从活但不可用
  • RestTemplate发送请求使用总结

    一 注入RestTemplate配置类 Rest配置类 Configuration public class RestTemplateConfiguration LoadBalanced Bean public RestTemplate r
  • 【器件选型】TVS二极管在复杂电路中的三大应用

    欢迎关注 玩转单片机与嵌入式 公号 回复关键字获取更多免费视频和资料 回复 加群 单片机 STM32 硬件知识 硬件设计 经典电路 论文 毕业设计 3D封装库 PCB 电容 TVS 阻抗匹配 资料 终端电阻 Keil 485 CAN 振荡器
  • Spark Streaming实现WordCount

    利用Spark Streaming实现WordCount 需求 监听某个端口上的网络数据 实时统计出现的不同单词个数 1 需要安装一个nc工具 sudo yum install y nc 2 执行指令 nc lk 9999 v import
  • 纯JS实现购物车&jQuery实现购物车

    目录 案例 纯JS实现购物车 主要功能 案例 jQuery实现购物车 主要功能 案例 纯JS实现购物车 主要功能 全选 全不选 单个删除 批量删除 数量的增减 合计
  • 机器学习 day33(误差分析、添加数据、迁移学习)

    误差分析 我们可以手动查看分类错误的子集样本 通常为100个 并统计他们的错误类型 在所有错误类型中 选择一种或几种最常见的错误 进行改进 这可以最高效的改进你的模型 误差分析的一个限制是 它只能很好的解决人类擅长的问题 添加数据 添加数据
  • 2.6 内核 tasklet 和workqueue 的区别

    work queue 跟tasklet 不同 1 work queue 运行环境的是内核线程 所以可以休眠 可以分配内存 获得信号量 执行阻塞I O 2 tasklet 的运行环境是软中断 所以不能休眠 3 tasklet的使用跟timer
  • 串口异步通信——时序宽度测试

    一般情况下串口 bit 1 与 bit 0 宽度能基本维持对等 脉宽接近 把串口 0x55 理解为一个占空比为50 的方波 在占空比接近50 的情况下 通信一般不会出现错误 但是 在一些脉宽有损失的场景中 则非常需要注意脉冲宽度要求 使用波
  • Unity中射线Ray和RaycastHit的简单介绍

    射线是在三维世界中从一个点沿一个方向发射的一条无限长的线 在射线的轨迹上 一旦与添加了碰撞器的模型发生碰撞 将停止发射 我们可以利用射线实现子弹击中目标的检测 鼠标点击拾取物体等功能 1 Physics Raycast public sta
  • pycharm修改快捷键

    pycharm修改快捷键 很多使用使用pythcharm的同学 如果想运行程序 通常需要 第一步右键 第二步 选择运行或者直接点击运行 但是往往厉害的程序员 一般直接键盘操作 如果你使用pycharm自带的快捷键 需要按下 Ctrl Shi
  • Python3 使用 selenium 获取 JS 代码里边的变量值

    from selenium import webdriver driver webdriver Ie r IEDriverServer exe 找一个合适版本的IEDriver js var hello hello world return
  • C语言实验——大小写转换oj1168

    C语言实验 大小写转换 Time Limit 1000ms Memory limit 65536K 有疑问 点这里 题目描述 把一个字符串里所有的大写字母换成小写字母 小写字母换成大写字母 其他字符保持不变 输入 输入为一行字符串 其中不含
  • 数据结构与算法 -- 基础篇

    本文主要用于记录学习过程中的一些总结 适用于一些刚学习数据结构和算法的同学 能够给予一些概括性认识 而且从下面的一些算法题中能够获得一些对于算法题目常用解题思路 如果能够对你有些帮助 是我之幸 接下来 将一共分为三部分来介绍如下内容 1 基
  • ElasticSearch 数据迁移方案

    一个人不论赋有什么样的棋 他如果不知道自己有这种棋 并且不形成适合于自己棋的计划 那种棋对他便完全无用 休漠 ElasticSearch 常用api ElasticSearch 版本说明 name node 3 cluster name t
  • python3 题解(10)打印金字塔1

    打印金字塔1 问题 用星号在控制台上输出一个金字塔的形状 可以看出 它的第n行的星号的个数是 2 n 1 这个问题的思路可以很多 比如 先造出指定数目的星号 再计算出前后补的空格数 这里采用如下的思路 已知了n 最后一行的星号的数目就固定了
  • 杭电ACM-A+B problem

    topic Calculate A B Input Each line will contain two integers A and B Process to end of file Output For each case output
  • QT QDockWidget 重叠方法

    主要通过如下红色代码的方法实现 效果图片如下 代码如下 void MainWindow createDockWindows QDockWidget dock new QDockWidget tr Customers this dock gt
  • curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to raw.githubusercontent.com:443

    MacOS系统使用 Homebrew 官方地址时 报错 Mac安装homebrew的时候报错 Mac bin bash c curl fsSL https raw githubusercontent com Homebrew install
  • 自定义openwrt的配置界面:luci进阶之路

    5 20 晴 今天的太阳挺大的 晒得我进园区直接37 3警告 于是我百度搜索微信朋友圈怎么关闭 才把温度稳定下来 算了算了 上班说事 由于公司部门调动 逐渐接触到新的知识 新的模块 还听说这玩意比较冷门 没办法 该搞还是得搞 又不是搞不了