今天才知道,非箭头函数和非 native 函数都可以作为构造函数
所以可以用一个匿名构造函数来创建一个匿名对象:`new function() { ... }`
我甚至查不到相关的说法,只看到有一个 stackoverflow 问题: https://stackoverflow.com/questions/40096704/new-function-vs-new-function
然后,会发生什么事情呢,调用了 bind()函数绑定了 this 值的函数也可以用一个新的空对象去调用,本来连 apply 和 call 都无法更改 this 值的:
```
function test() {
console.log('调用 test()函数, this 值是:', this);
}
test = test.bind({ a: 1 });
test();
new test();
```
真的太容易混淆了吧:
```
typeof Function
'function'
typeof function() {}
'function'
typeof new Function
'function'
typeof new function() {}
'object'
```
#function #new #test #typeof #调用 #stackoverflow #bind #Function #函数 #匿名
所以可以用一个匿名构造函数来创建一个匿名对象:`new function() { ... }`
我甚至查不到相关的说法,只看到有一个 stackoverflow 问题: https://stackoverflow.com/questions/40096704/new-function-vs-new-function
然后,会发生什么事情呢,调用了 bind()函数绑定了 this 值的函数也可以用一个新的空对象去调用,本来连 apply 和 call 都无法更改 this 值的:
```
function test() {
console.log('调用 test()函数, this 值是:', this);
}
test = test.bind({ a: 1 });
test();
new test();
```
真的太容易混淆了吧:
```
typeof Function
'function'
typeof function() {}
'function'
typeof new Function
'function'
typeof new function() {}
'object'
```
#function #new #test #typeof #调用 #stackoverflow #bind #Function #函数 #匿名
前端如何获得某个函数的完全实现?
项目中前端实现了某个复杂的渲染逻辑(渲染的结果是字符串,可以理解是多字段的复杂组装),现在要把这个渲染逻辑挪到后端
由于渲染逻辑比较复杂,如果后端独立实现这个渲染逻辑,相当于一件事情做了两遍,未免太花时间
所以现在需要把前端的渲染逻辑整理一下,直接把相关函数给到后端使用
但是前端这个函数调用了其他的好多子函数,试了一下直接使用 [Function.prototype.toString]( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString),但结果并不能包含它所依赖的子函数的函数体。
想来请教下前端如何能够能够完整的输出这个渲染函数呢?可以是一个巨大无比的函数,也可以是一个文件里面好多函数,但要保证函数间的依赖完整
FYI: 前端用的是 webpack 做打包,语言是 typescript
#渲染 #函数 #前端 #逻辑 #子函数 #Function #toString #好多 #这个 #依赖
项目中前端实现了某个复杂的渲染逻辑(渲染的结果是字符串,可以理解是多字段的复杂组装),现在要把这个渲染逻辑挪到后端
由于渲染逻辑比较复杂,如果后端独立实现这个渲染逻辑,相当于一件事情做了两遍,未免太花时间
所以现在需要把前端的渲染逻辑整理一下,直接把相关函数给到后端使用
但是前端这个函数调用了其他的好多子函数,试了一下直接使用 [Function.prototype.toString]( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString),但结果并不能包含它所依赖的子函数的函数体。
想来请教下前端如何能够能够完整的输出这个渲染函数呢?可以是一个巨大无比的函数,也可以是一个文件里面好多函数,但要保证函数间的依赖完整
FYI: 前端用的是 webpack 做打包,语言是 typescript
#渲染 #函数 #前端 #逻辑 #子函数 #Function #toString #好多 #这个 #依赖
试着用 luv 写个读取文件内容方法,实在是写不下去
```
local uv = vim.loop
local readall = function(path, callback)
uv.fs_open(path, "r", 384, function(open_err, fd)
assert(open_err == nil, open_err)
uv.fs_stat(path, function(stat_err, stat)
assert(stat_err == nil, stat_err)
uv.fs_read(fd, stat.size, 0, function(read_err, data)
assert(read_err == nil, read_err)
assert(#data == stat.size)
uv.fs_close(fd, function(close_err, success)
assert(close_err == nil, close_err)
assert(success)
callback(data)
end)
end)
end)
end)
end
readall("/tmp/seq30", function(data)
for _, line in ipairs(vim.split(data, "\n")) do
print(line)
end
end)
```
贴出来给大家瞅瞅啊。
其实就一个 `io.lines(path)`,写完上面这篇代码我不由得犹豫,我就写个小插件,有必要强上异步吗?
还只是个这么简单的需求。
( vim.loop 是 neovim 提供的 libuv/luv 访问入口)
#err #stat #end #function #assert #uv #data #path #fs #open
```
local uv = vim.loop
local readall = function(path, callback)
uv.fs_open(path, "r", 384, function(open_err, fd)
assert(open_err == nil, open_err)
uv.fs_stat(path, function(stat_err, stat)
assert(stat_err == nil, stat_err)
uv.fs_read(fd, stat.size, 0, function(read_err, data)
assert(read_err == nil, read_err)
assert(#data == stat.size)
uv.fs_close(fd, function(close_err, success)
assert(close_err == nil, close_err)
assert(success)
callback(data)
end)
end)
end)
end)
end
readall("/tmp/seq30", function(data)
for _, line in ipairs(vim.split(data, "\n")) do
print(line)
end
end)
```
贴出来给大家瞅瞅啊。
其实就一个 `io.lines(path)`,写完上面这篇代码我不由得犹豫,我就写个小插件,有必要强上异步吗?
还只是个这么简单的需求。
( vim.loop 是 neovim 提供的 libuv/luv 访问入口)
#err #stat #end #function #assert #uv #data #path #fs #open
JavaScript 防抖函数,绑定事件后事件对象传参问题
明明事件对象 e 是作为的 debounce 中的第一个 fn 函数参数,为什么能够被 debounce 函数返回的匿名函数中
的...args 获取得到呢?实在想不通,不知道有哪位同学可以答疑解惑,不胜感激
```
// 防抖
function debounce(func, wait = 500) {
let timeID;
return function (...args) {
if (timeID) clearTimeout(timeID);
timeID = setTimeout(() => {
func.apply(this, args);
}, wait);
}
}
let password = document.querySelector('[name="password"]');
// 明明事件对象 e 是作为的 debounce 中的第一个 fn 函数参数,为什么能够被 debounce 函数返回的匿名函数中
// 的...args 获取得到呢?实在想不通,不知道有哪位同学可以答疑解惑,不胜感激
password.addEventListener("keyup", debounce(function (e) {
console.log(222)
}, 500));
```
#debounce #args #timeID #... #function #password #函数 #函数参数 #fn #func
明明事件对象 e 是作为的 debounce 中的第一个 fn 函数参数,为什么能够被 debounce 函数返回的匿名函数中
的...args 获取得到呢?实在想不通,不知道有哪位同学可以答疑解惑,不胜感激
```
// 防抖
function debounce(func, wait = 500) {
let timeID;
return function (...args) {
if (timeID) clearTimeout(timeID);
timeID = setTimeout(() => {
func.apply(this, args);
}, wait);
}
}
let password = document.querySelector('[name="password"]');
// 明明事件对象 e 是作为的 debounce 中的第一个 fn 函数参数,为什么能够被 debounce 函数返回的匿名函数中
// 的...args 获取得到呢?实在想不通,不知道有哪位同学可以答疑解惑,不胜感激
password.addEventListener("keyup", debounce(function (e) {
console.log(222)
}, 500));
```
#debounce #args #timeID #... #function #password #函数 #函数参数 #fn #func
有将 JS(非 TypeScript)编译成 wasm 然后用 JS 的 WebAssembly 接口调用的成功案例吗?
公司想尝试用 wasm 作为 js 代码保护的一种方式
如果确实不可行请敲醒我,我知道 wasm 本身不应该是这么用的
目前试了一下: https://github.com/Shopify/javy
按照他的教程编译后用 wasmtime 确实可以运行,但是用 JS 的 WebAssembly 接口调用就会报错:
```js
WebAssembly.instantiateStreaming(fetch("xxxxxxx/index.wasm"), {
wasi_snapshot_preview1: {
fd_close: (e) => {
console.log("fd_close", e);
},
fd_write: (e) => {
console.log("fd_write", e);
},
fd_read: (e) => {
console.log("fd_read", e);
},
fd_seek: (e) => {
console.log("fd_seek", e);
},
environ_get: (e) => {
console.log("fd_environ_get", e);
},
environ_sizes_get: (e) => {
console.log("fd_environ_sizes_get", e);
},
clock_time_get: (e) => {
console.log("clock_time_get", e);
},
fd_fdstat_get: (e) => {
console.log("fd_fdstat_get", e);
},
proc_exit: (e) => {
console.log("proc_exit", e);
},
},
env: {},
}).then((obj) => {
console.log(obj.instance.exports.main({ n: 100, bar: "test" }));
});
```
```txt
RuntimeError: unreachable
at xxxxxxx/index.wasm:wasm-function[193]:0x110ec
at xxxxxxx/index.wasm:wasm-function[318]:0x1a4fc
at xxxxxxx/index.wasm:wasm-function[28]:0x1489
at xxxxxxx/index.wasm:wasm-function[88]:0x728f
at xxxxxxx/index.wasm:wasm-function[57]:0x38ab
at xxxxxxx/index.wasm:wasm-function[287]:0x18880
at xxxxxxx/index.wasm:wasm-function[39]:0x1cb6
at xxxxxxx/index.wasm:wasm-function[193]:0x11422
at xxxxxxx/index.wasm:wasm-function[318]:0x1a4fc
at xxxxxxx/index.wasm:wasm-function[28]:0x1489
```
#wasm #fd #xxxxxxx #index #console #log #function #get #environ #js
公司想尝试用 wasm 作为 js 代码保护的一种方式
如果确实不可行请敲醒我,我知道 wasm 本身不应该是这么用的
目前试了一下: https://github.com/Shopify/javy
按照他的教程编译后用 wasmtime 确实可以运行,但是用 JS 的 WebAssembly 接口调用就会报错:
```js
WebAssembly.instantiateStreaming(fetch("xxxxxxx/index.wasm"), {
wasi_snapshot_preview1: {
fd_close: (e) => {
console.log("fd_close", e);
},
fd_write: (e) => {
console.log("fd_write", e);
},
fd_read: (e) => {
console.log("fd_read", e);
},
fd_seek: (e) => {
console.log("fd_seek", e);
},
environ_get: (e) => {
console.log("fd_environ_get", e);
},
environ_sizes_get: (e) => {
console.log("fd_environ_sizes_get", e);
},
clock_time_get: (e) => {
console.log("clock_time_get", e);
},
fd_fdstat_get: (e) => {
console.log("fd_fdstat_get", e);
},
proc_exit: (e) => {
console.log("proc_exit", e);
},
},
env: {},
}).then((obj) => {
console.log(obj.instance.exports.main({ n: 100, bar: "test" }));
});
```
```txt
RuntimeError: unreachable
at xxxxxxx/index.wasm:wasm-function[193]:0x110ec
at xxxxxxx/index.wasm:wasm-function[318]:0x1a4fc
at xxxxxxx/index.wasm:wasm-function[28]:0x1489
at xxxxxxx/index.wasm:wasm-function[88]:0x728f
at xxxxxxx/index.wasm:wasm-function[57]:0x38ab
at xxxxxxx/index.wasm:wasm-function[287]:0x18880
at xxxxxxx/index.wasm:wasm-function[39]:0x1cb6
at xxxxxxx/index.wasm:wasm-function[193]:0x11422
at xxxxxxx/index.wasm:wasm-function[318]:0x1a4fc
at xxxxxxx/index.wasm:wasm-function[28]:0x1489
```
#wasm #fd #xxxxxxx #index #console #log #function #get #environ #js
JavaScript 函数无法读取到函数外的变量是什么原因?
为什么 createDomTree 无法获取到 test 这个变量? test 是定义在 createDomTree()之外的。
#test #createDomTree #app #sidebar #pre #function #console #log #new #var
为什么 createDomTree 无法获取到 test 这个变量? test 是定义在 createDomTree()之外的。
var app = function() {
this.sidebar = {
test: 1,
createDomTree: function() {
console.log(test)
}
}
}
console.log(new app().sidebar); // {test: 1, createDomTree: ƒ}
new app().sidebar.createDomTree(); // Uncaught ReferenceError: test is not defined
#test #createDomTree #app #sidebar #pre #function #console #log #new #var
小程序 globalData undefined 如何解决
```//封装 wx.request()
function request(requestMapping, data, requestWay, contentType) {
wx.showLoading({
title: '请稍后',
})
return new Promise(function(resolve, reject) {
console.log('请求中。。。。。')
wx.request({
url: '自己的服务器地址' + requestMapping,
data: data,
header: {
'content-type': contentType // 默认值
},
timeout: 3000,
method: requestWay,
success(res) {
//console.log(res)
if (res.data.success == false || res.data.statusCode == 404) {
reject(res)
} else {
resolve(res)
}
},
fail: (e) => {
wx.showToast({
title: '连接失败',
icon: 'none'
})},
complete: () => {
wx.hideLoading()
}
})
})
}
//获取 openid
function getOpenId(app, that){
return new Promise(function (resolve, reject) {
wx.login({
success: function (yes) {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
var requestMapping = '/testopenid'
var data = {
code: yes.code
}
var requestWay = 'GET'
var contentType = 'application/json'
var p =request(requestMapping, data, requestWay, contentType)
p.then(res => {
//console.log(res) 做一些后续操作
app.globalData.openId = res.data;
resolve(res)
}).catch(e => {
reject(e)
})
},
fail(e) {
console.log(e)
}
})
})
}
```
getOpenId(getApp(),this);

#res #data #wx #function #var #request #requestMapping #requestWay #contentType #resolve
```//封装 wx.request()
function request(requestMapping, data, requestWay, contentType) {
wx.showLoading({
title: '请稍后',
})
return new Promise(function(resolve, reject) {
console.log('请求中。。。。。')
wx.request({
url: '自己的服务器地址' + requestMapping,
data: data,
header: {
'content-type': contentType // 默认值
},
timeout: 3000,
method: requestWay,
success(res) {
//console.log(res)
if (res.data.success == false || res.data.statusCode == 404) {
reject(res)
} else {
resolve(res)
}
},
fail: (e) => {
wx.showToast({
title: '连接失败',
icon: 'none'
})},
complete: () => {
wx.hideLoading()
}
})
})
}
//获取 openid
function getOpenId(app, that){
return new Promise(function (resolve, reject) {
wx.login({
success: function (yes) {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
var requestMapping = '/testopenid'
var data = {
code: yes.code
}
var requestWay = 'GET'
var contentType = 'application/json'
var p =request(requestMapping, data, requestWay, contentType)
p.then(res => {
//console.log(res) 做一些后续操作
app.globalData.openId = res.data;
resolve(res)
}).catch(e => {
reject(e)
})
},
fail(e) {
console.log(e)
}
})
})
}
```
getOpenId(getApp(),this);

#res #data #wx #function #var #request #requestMapping #requestWay #contentType #resolve
请教大佬 js 和 Python 鼠标单击和双击 callback 问题
下面是 dash—tabulator JS 里鼠标单击和双击 callback 设置代码,
window.myNamespace = Object.assign({}, window.myNamespace, {
tabulator: {
cellClick: function (e, cell, table) {
// console.log(cell)
table.props.setProps({"cellClick" : [cell._cell.column.field, cell._cell.row.data]})
},
cellDblClick: function (e, cell, table) {
// console.log(cell)
table.props.setProps({"cellDblClick" : [cell._cell.column.field, cell._cell.row.data]})
}
}
});
python 里代码如下
@app.callback(
[Output("app-content", "children")],
[Input('tabulator', 'cellClick'), Input('tabulator', 'cellDblClick')],
prevent_initial_call=True,
)
def function(cell_cllick,cell_dbl_click):
pass
问题是鼠标单击优先级高于双击,如果我同时设置点击表格事件,单击肯定触发,双击设置就无效了。
如果 js 里单击事件加上延迟,哪怕 1ms 延迟,python 里单击 callback 又无法生效,请教大佬们是如何解决优先级问题的
#cell #单击 #tabulator #table #._ #双击 #callback #cellClick #function #cellDblClick
下面是 dash—tabulator JS 里鼠标单击和双击 callback 设置代码,
window.myNamespace = Object.assign({}, window.myNamespace, {
tabulator: {
cellClick: function (e, cell, table) {
// console.log(cell)
table.props.setProps({"cellClick" : [cell._cell.column.field, cell._cell.row.data]})
},
cellDblClick: function (e, cell, table) {
// console.log(cell)
table.props.setProps({"cellDblClick" : [cell._cell.column.field, cell._cell.row.data]})
}
}
});
python 里代码如下
@app.callback(
[Output("app-content", "children")],
[Input('tabulator', 'cellClick'), Input('tabulator', 'cellDblClick')],
prevent_initial_call=True,
)
def function(cell_cllick,cell_dbl_click):
pass
问题是鼠标单击优先级高于双击,如果我同时设置点击表格事件,单击肯定触发,双击设置就无效了。
如果 js 里单击事件加上延迟,哪怕 1ms 延迟,python 里单击 callback 又无法生效,请教大佬们是如何解决优先级问题的
#cell #单击 #tabulator #table #._ #双击 #callback #cellClick #function #cellDblClick
vercel + mongo + jquery 搭建无需注册的免费在线笔记网站
## 主要功能:免注册 ,一个 url 地址或者 6 位验证码, 在手机或者电脑可以直接打开编辑的在线文本。
体验网站 https://doc.op52.com/
开源代码 https://github.com/tans/online-editor.git
通过 vercel 的 serverless function 和 saas 版 mongodb 的免费 quota ,搭建了一个在线文本笔记网站。
vercel 相当于主机, 可以托管静态文件和 serverless function 。
mongo 提供一个 10G 的免费 quota 。
个人主要当粘贴板和共享文档用。
一点开发心得
1. vercel 的 serverless function 很方便, 放个 js 文件到 api 文件夹, 就是一个接口, 文件路径就是接口路径, 貌似支持所有 http method 调用。
2. mongo 的 saas 版本本地连接有点难链上, 经常遇到 socket hangup 。
3. jquery 很久没用了,交互处理确实不方便,习惯了基于状态的开发, 到处写事件绑定有点恶心。 但胜在细节处理方便。比如 textarea 动态高度,不知道 vue 和 react 怎么处理。 本来不打算做成大项目,jquery 勉强够用。
4. 本项目没有用 next 框架, 算是 vercel 的最简单的使用方法了,没有被隐藏的技术细节, 十分适合上手 serverless 项目用。
欢迎大家提 各种产品的 features 和 bug 。
#vercel #serverless #function #https #com #saas #quota #mongo #jquery #方便
## 主要功能:免注册 ,一个 url 地址或者 6 位验证码, 在手机或者电脑可以直接打开编辑的在线文本。
体验网站 https://doc.op52.com/
开源代码 https://github.com/tans/online-editor.git
通过 vercel 的 serverless function 和 saas 版 mongodb 的免费 quota ,搭建了一个在线文本笔记网站。
vercel 相当于主机, 可以托管静态文件和 serverless function 。
mongo 提供一个 10G 的免费 quota 。
个人主要当粘贴板和共享文档用。
一点开发心得
1. vercel 的 serverless function 很方便, 放个 js 文件到 api 文件夹, 就是一个接口, 文件路径就是接口路径, 貌似支持所有 http method 调用。
2. mongo 的 saas 版本本地连接有点难链上, 经常遇到 socket hangup 。
3. jquery 很久没用了,交互处理确实不方便,习惯了基于状态的开发, 到处写事件绑定有点恶心。 但胜在细节处理方便。比如 textarea 动态高度,不知道 vue 和 react 怎么处理。 本来不打算做成大项目,jquery 勉强够用。
4. 本项目没有用 next 框架, 算是 vercel 的最简单的使用方法了,没有被隐藏的技术细节, 十分适合上手 serverless 项目用。
欢迎大家提 各种产品的 features 和 bug 。
#vercel #serverless #function #https #com #saas #quota #mongo #jquery #方便
typescripr 中,如何写能随意组合函数参数并且能得到对应类型的提示
如何定义一个函数有 4 个参数(一个必选,三个可选),能随意组合参数并且能得到对应类型的提示
```
function name ( url,params:type ){}
function name ( url,params:type,config ){}
function name ( url,params:type,config,option ){}
```
用的时候
```
name('http',{params}) 或
name('http',{config}) 或
name('http',{option }) 或
name('http',{params}, {option }) 或
name('http',{config}, {option })
```
#name #params #http #config #option #function #url #type #参数 #必选
如何定义一个函数有 4 个参数(一个必选,三个可选),能随意组合参数并且能得到对应类型的提示
```
function name ( url,params:type ){}
function name ( url,params:type,config ){}
function name ( url,params:type,config,option ){}
```
用的时候
```
name('http',{params}) 或
name('http',{config}) 或
name('http',{option }) 或
name('http',{params}, {option }) 或
name('http',{config}, {option })
```
#name #params #http #config #option #function #url #type #参数 #必选
PHP 这种查询怎么能写的好看点,优雅点,高级点呢
代码如下(这是 thinkphp 写的):
```php
return $this->alias('cus')
->join('admin a', 'cus.userID = a.id')
->field('cus.userID,a.cjName,count(*) AS count')
->when($month, function ($query) use ($month) {
$query->whereMonth('cjTime', $month);
},function ($query) {
$query->whereYear('cjTime', date('Y'));
})
->when($brand_id, function ($query) use ($brand_id) {
$query->where('cus.cjbrandID', $brand_id);
})
->when($shop_id, function ($query) use ($shop_id) {
$query->where('cus.cjMenDian', $shop_id);
})
->group('cus.userID')
->order('count desc')
->limit(10)
->select()->each(function ($item) {
// ....
return $item;
})->toArray();
```
#query #id #cus #function #userID #count #when #month #use #brand
代码如下(这是 thinkphp 写的):
```php
return $this->alias('cus')
->join('admin a', 'cus.userID = a.id')
->field('cus.userID,a.cjName,count(*) AS count')
->when($month, function ($query) use ($month) {
$query->whereMonth('cjTime', $month);
},function ($query) {
$query->whereYear('cjTime', date('Y'));
})
->when($brand_id, function ($query) use ($brand_id) {
$query->where('cus.cjbrandID', $brand_id);
})
->when($shop_id, function ($query) use ($shop_id) {
$query->where('cus.cjMenDian', $shop_id);
})
->group('cus.userID')
->order('count desc')
->limit(10)
->select()->each(function ($item) {
// ....
return $item;
})->toArray();
```
#query #id #cus #function #userID #count #when #month #use #brand
if(num ==0 || num ==null) num == null can not reach always false
Integer num = 0;
Integer num = xxxDao.select(); // 无结果 返回 null
if(num == 0 || num == null){
num = num2; //num2 就是一个其他非空的值
}
// 此时调用方法
function(num) throw NullPointerExcepiton
我改成 if(Objects.isNull(num) || num == 0) 才不会报空
idea 提示 num == null can not reach always false.
这是啥原因?有没有大佬知道
#num #null #Integer #num2 #xxxDao #select #非空 #function #throw #NullPointerExcepiton
Integer num = 0;
Integer num = xxxDao.select(); // 无结果 返回 null
if(num == 0 || num == null){
num = num2; //num2 就是一个其他非空的值
}
// 此时调用方法
function(num) throw NullPointerExcepiton
我改成 if(Objects.isNull(num) || num == 0) 才不会报空
idea 提示 num == null can not reach always false.
这是啥原因?有没有大佬知道
#num #null #Integer #num2 #xxxDao #select #非空 #function #throw #NullPointerExcepiton
分享一个 AIR724(电信卡)利用 bark 短信转发的操作, AIR780E 或许也能直接用
前些天跟风上车了 AIR780E ,到手发现不支持电信短信转发,再加上官方二次开发也没放出来(官网显示 11 月 13 号放出),直接吃灰,立马入了个 AIR724 (外接电源工业应用铁盒那种),724 支持电信 VoLTE 状态下的短信收发,最好选择带 USB 接口调试这种,方便固件和脚本的刷写。
参考了几位大佬的脚本,谢谢大佬们的示范,我做了点微不足道的复制粘贴工作
使用 Air724ug 开发板进行短信转发 https://web.archive.org/web/20221026074816/https://blog.okwlan.com/article/air724ug.html
使用 Air724UG 作为短信转发器
https://www.lotlab.org/2021/10/17/air724ug-sms-forwarder/
air724UG + Luat 玩转物联网(一) 环境搭建及固件烧录
https://www.jianshu.com/p/1f7043fff6de
准备工作:
1 、724 模块+天线+电源+数据线+驱动+luatoolsV2 调试软件
2 、电信卡(带流量,利用自身流量转发到 bark )
3 、已部署好的 bark 服务器地址
实际操作( WIN7 驱动支持不好,工具显示不正常,建议 WIN10 操作):
1 、装好驱动打开 luatools 对模块进行刷机
选择 luatools\resource\8910_lua_lod\core_V4018\LuatOS-Air_V4018_RDA8910_TTS_NOLVGL_FLOAT.pac 进行下载,重启后进行下一步
2 、烧写脚本
进入项目管理测试里新建一个项目名称( SMS 之类的)
底层 core 选择 luatools\resource\8910_lua_lod\core_V4018\LuatOS-Air_V4018_RDA8910_TTS_NOLVGL_FLOAT.pac
脚本文件选择 luatools\resource\8910_script\script_LuaTask_V2.4.3\demo\sms 下面的 main.lua 和 testSms.lua 并对 testSms.lua 脚本文件做以下编辑,并把第三行的 BARK_URL 替换成自己的:
PROJECT = "SMS_Forwarder"
VERSION = "1.0.0"
BARK_URL = "http://XXX.XXX.XXX.XXX:8080/ABCDEFGHIJK/" -- 替换成自己的 bark 推送地址
require "sys"
require "http"
require "sms"
require "common"
require "cc"
require "audio"
require "net"
-- HTTP 回调,显示调试信息用
function httpCallback(result, prompt, head, body)
if result then
print("HTTP", prompt, body)
else
print("HTTP Request Failed. ", prompt)
end
end
-- 将消息发送到你的平台
function notifyToBark(msg)
http.request(
"GET",
-- BARK_URL..string.urlEncode(msg),
BARK_URL..string.rawurlEncode(msg), -- 对内容中文进行编码
nil, -- 不指定证书
nil,
nil,
30000, -- 发送超时,ms
httpCallback, -- 回调
nil
)
end
--[[
num:短信号码,ASCII 码字符串格式
data:短信内容,字符串格式
datetime:短信日期和时间,ASCII 码字符串格式
]]
function smsCallback(num, data, datetime)
print("SMS FROM ", num, " IN ", datetime)
print(data)
data = common.gb2312ToUtf8(data) -- 短信编码要转换为目标平台支持的 UTF-8
data = string.gsub(data, "*", "\\*") -- Telegram 特殊字符转义
data = string.gsub(data, "_", "\\_") -- Telegram 特殊字符转义
notifyToBark(num.." ("..datetime.."):\r\n"..data)
end
call_in = false
-- 电话拨入回调,在这里发送通知并接通电话
function call_incoming(num)
print("CALL FROM ", num)
if not call_in then
call_in = true
notifyToBark(num.." 给您来电")
cc.accept(num)
end
end
-- 电话接通回调,这里播放 TTS 通知对方
function call_connected(num)
print("CALL CONNECTED")
call_in = false
--通话中向对方播放 TTS
audio.play(7,"TTS","您好,机主无法接听您的来电,请使用短信联系机主。",7,nil,true,2000)
--30 秒之后主动结束通话
sys.timerStart(cc.hangUp,30000,num)
end
-- 电话挂断回调,停止 TTS
function call_disconnected(discReason)
print("CALL DISCONNECTED")
call_in = false
sys.timerStopAll(cc.hangUp)
audio.stop()
end
-- 定时任务:每天发送短信到 10001 查询流量
sys.timerLoopStart(
function()
sms.send("10001", "108", nil, nil)
end
, 24*60*60*1000
)
--加载网络指示灯和 LTE 指示灯功能模块
--根据自己的项目需求和硬件配置决定:1 、是否加载此功能模块; 2 、配置指示灯引脚
--合宙官方出售的 Air720U 开发板上的网络指示灯引脚为 pio.P0_1 ,LTE 指示灯引脚为 pio.P0_4
require "netLed"
pmd.ldoset(2,pmd.LDO_VLCD)
netLed.setup(true,pio.P0_1,pio.P0_4)
--设置短信回调
sms.setNewSmsCb(smsCallback)
--禁用 RNDIS ,防止跑流量
ril.request("AT+RNDISCALL=0,1")
--注册电话回调
sys.subscribe("CALL_INCOMING", call_incoming)
sys.subscribe("CALL_CONNECTED", call_connected)
sys.subscribe("CALL_DISCONNECTED", call_disconnected)
--每 1 分钟查询一次 GSM 信号强度
--每 1 分钟查询一次基站信息
net.startQueryAll(60000, 60000)
-- 系统初始化
sys.init(0, 0)
sys.run()
勾选 usb 打印 trace 、添加默认 lib 、升级文件包含脚本
选择下载脚本,7-8S 和显示成功,会自动重启,等个半分钟左右就可以发短信和打电话测试了
#-- #call #num #data #sys #end #require #短信 #function #print
前些天跟风上车了 AIR780E ,到手发现不支持电信短信转发,再加上官方二次开发也没放出来(官网显示 11 月 13 号放出),直接吃灰,立马入了个 AIR724 (外接电源工业应用铁盒那种),724 支持电信 VoLTE 状态下的短信收发,最好选择带 USB 接口调试这种,方便固件和脚本的刷写。
参考了几位大佬的脚本,谢谢大佬们的示范,我做了点微不足道的复制粘贴工作
使用 Air724ug 开发板进行短信转发 https://web.archive.org/web/20221026074816/https://blog.okwlan.com/article/air724ug.html
使用 Air724UG 作为短信转发器
https://www.lotlab.org/2021/10/17/air724ug-sms-forwarder/
air724UG + Luat 玩转物联网(一) 环境搭建及固件烧录
https://www.jianshu.com/p/1f7043fff6de
准备工作:
1 、724 模块+天线+电源+数据线+驱动+luatoolsV2 调试软件
2 、电信卡(带流量,利用自身流量转发到 bark )
3 、已部署好的 bark 服务器地址
实际操作( WIN7 驱动支持不好,工具显示不正常,建议 WIN10 操作):
1 、装好驱动打开 luatools 对模块进行刷机
选择 luatools\resource\8910_lua_lod\core_V4018\LuatOS-Air_V4018_RDA8910_TTS_NOLVGL_FLOAT.pac 进行下载,重启后进行下一步
2 、烧写脚本
进入项目管理测试里新建一个项目名称( SMS 之类的)
底层 core 选择 luatools\resource\8910_lua_lod\core_V4018\LuatOS-Air_V4018_RDA8910_TTS_NOLVGL_FLOAT.pac
脚本文件选择 luatools\resource\8910_script\script_LuaTask_V2.4.3\demo\sms 下面的 main.lua 和 testSms.lua 并对 testSms.lua 脚本文件做以下编辑,并把第三行的 BARK_URL 替换成自己的:
PROJECT = "SMS_Forwarder"
VERSION = "1.0.0"
BARK_URL = "http://XXX.XXX.XXX.XXX:8080/ABCDEFGHIJK/" -- 替换成自己的 bark 推送地址
require "sys"
require "http"
require "sms"
require "common"
require "cc"
require "audio"
require "net"
-- HTTP 回调,显示调试信息用
function httpCallback(result, prompt, head, body)
if result then
print("HTTP", prompt, body)
else
print("HTTP Request Failed. ", prompt)
end
end
-- 将消息发送到你的平台
function notifyToBark(msg)
http.request(
"GET",
-- BARK_URL..string.urlEncode(msg),
BARK_URL..string.rawurlEncode(msg), -- 对内容中文进行编码
nil, -- 不指定证书
nil,
nil,
30000, -- 发送超时,ms
httpCallback, -- 回调
nil
)
end
--[[
num:短信号码,ASCII 码字符串格式
data:短信内容,字符串格式
datetime:短信日期和时间,ASCII 码字符串格式
]]
function smsCallback(num, data, datetime)
print("SMS FROM ", num, " IN ", datetime)
print(data)
data = common.gb2312ToUtf8(data) -- 短信编码要转换为目标平台支持的 UTF-8
data = string.gsub(data, "*", "\\*") -- Telegram 特殊字符转义
data = string.gsub(data, "_", "\\_") -- Telegram 特殊字符转义
notifyToBark(num.." ("..datetime.."):\r\n"..data)
end
call_in = false
-- 电话拨入回调,在这里发送通知并接通电话
function call_incoming(num)
print("CALL FROM ", num)
if not call_in then
call_in = true
notifyToBark(num.." 给您来电")
cc.accept(num)
end
end
-- 电话接通回调,这里播放 TTS 通知对方
function call_connected(num)
print("CALL CONNECTED")
call_in = false
--通话中向对方播放 TTS
audio.play(7,"TTS","您好,机主无法接听您的来电,请使用短信联系机主。",7,nil,true,2000)
--30 秒之后主动结束通话
sys.timerStart(cc.hangUp,30000,num)
end
-- 电话挂断回调,停止 TTS
function call_disconnected(discReason)
print("CALL DISCONNECTED")
call_in = false
sys.timerStopAll(cc.hangUp)
audio.stop()
end
-- 定时任务:每天发送短信到 10001 查询流量
sys.timerLoopStart(
function()
sms.send("10001", "108", nil, nil)
end
, 24*60*60*1000
)
--加载网络指示灯和 LTE 指示灯功能模块
--根据自己的项目需求和硬件配置决定:1 、是否加载此功能模块; 2 、配置指示灯引脚
--合宙官方出售的 Air720U 开发板上的网络指示灯引脚为 pio.P0_1 ,LTE 指示灯引脚为 pio.P0_4
require "netLed"
pmd.ldoset(2,pmd.LDO_VLCD)
netLed.setup(true,pio.P0_1,pio.P0_4)
--设置短信回调
sms.setNewSmsCb(smsCallback)
--禁用 RNDIS ,防止跑流量
ril.request("AT+RNDISCALL=0,1")
--注册电话回调
sys.subscribe("CALL_INCOMING", call_incoming)
sys.subscribe("CALL_CONNECTED", call_connected)
sys.subscribe("CALL_DISCONNECTED", call_disconnected)
--每 1 分钟查询一次 GSM 信号强度
--每 1 分钟查询一次基站信息
net.startQueryAll(60000, 60000)
-- 系统初始化
sys.init(0, 0)
sys.run()
勾选 usb 打印 trace 、添加默认 lib 、升级文件包含脚本
选择下载脚本,7-8S 和显示成功,会自动重启,等个半分钟左右就可以发短信和打电话测试了
#-- #call #num #data #sys #end #require #短信 #function #print
闭包怪异问题: 为啥这个闭包函数不缓存 count 值?
function createIncrement() {
let count = 0;
function increment() {
count++;
}
let message = `Count is ${count}`;
function log() {
console.log(message);
}
return [increment, log];
}
const [increment, log] = createIncrement();
increment();
increment();
increment();
log(); // What is logged?
问题
1. 为啥 log()输出 Count is 0?
increment 闭包 ha 函数为啥不缓存 count 的值?
2. 为啥把 let message = `Count is ${count}`移到 log 函数内就能输出 Count is 3?
function log() {
let message = `Count is ${count}`;
console.log(message);
}
#log #increment #count #message #Count #function #let #为啥 #createIncrement #console
function createIncrement() {
let count = 0;
function increment() {
count++;
}
let message = `Count is ${count}`;
function log() {
console.log(message);
}
return [increment, log];
}
const [increment, log] = createIncrement();
increment();
increment();
increment();
log(); // What is logged?
问题
1. 为啥 log()输出 Count is 0?
increment 闭包 ha 函数为啥不缓存 count 的值?
2. 为啥把 let message = `Count is ${count}`移到 log 函数内就能输出 Count is 3?
function log() {
let message = `Count is ${count}`;
console.log(message);
}
#log #increment #count #message #Count #function #let #为啥 #createIncrement #console
如何让视频带声音的自动播放?
网址: https://www.cgtn.com/tv
浏览器: chrome
以上网站打开后会自动播放视频, 但是静音, 俺想写一个油猴脚本让它有声音的自动播放, 脚本如下
```js
(function() {
'use strict';
// Your code here...
$(document).ready(function() {
setTimeout(() => {
jwplayer().setVolume(50);
jwplayer().play();
}, 2000);
});
})();
```
现在可以调整声音了, 但是调整声音后, 视频就自动暂停了, 在 console 有如下警告
> Unmuting failed and the element was paused instead because the user didn't interact with the document before.
俺不太懂前端, 现在的问题就是, 如何让它有声音的自动播放?
#自动播放 #function #document #jwplayer #声音 #视频 #脚本 #如下 #https #www
网址: https://www.cgtn.com/tv
浏览器: chrome
以上网站打开后会自动播放视频, 但是静音, 俺想写一个油猴脚本让它有声音的自动播放, 脚本如下
```js
(function() {
'use strict';
// Your code here...
$(document).ready(function() {
setTimeout(() => {
jwplayer().setVolume(50);
jwplayer().play();
}, 2000);
});
})();
```
现在可以调整声音了, 但是调整声音后, 视频就自动暂停了, 在 console 有如下警告
> Unmuting failed and the element was paused instead because the user didn't interact with the document before.
俺不太懂前端, 现在的问题就是, 如何让它有声音的自动播放?
#自动播放 #function #document #jwplayer #声音 #视频 #脚本 #如下 #https #www