GoAhead4.1.0 开发总结二(自定义使用)
环境
官方文档:https://www.embedthis.com/goahead/doc/
源码下载: goahead-4.1.0-src.tgz
系统平台:Ubuntu 12.04.4
gcc version 4.6.3
GoAhead自定义程序实现
goahead 源码提供了 test 示例代码,参照 test 代码框架实现 goahead 常用的 GoActions过程和embedded JavaScript 等
1.自定义代码编译与组成
本文实现的代码运行与 arm 平台,为了便于后面源码的编译,单独配置一个makefile配置文件 .mk 文件用于自定义程序的编译
复制 projects/goahead-linux-default.mk 重命名为 goahead-linux-arm-default.mk,并在此基础上做修改
后面每次编译采用指定文件的方式编译
make -f projects/goahead-linux-arm-default.mk
在 goahead-4.1.0 下新建 m283-webs 文件夹,里面存放自定义 web 代码,包含文件如下所示

goahead-linux-arm-default.mk 文件修改如下:
修改1:平台与配置
主要修改 ARCH(平台) CC(编译环境) 以及编译的常用配置,可以用于裁剪代码大小,本例先放弃SSL,因为这个比较占ROM
#
# goahead-linux-default.mk -- Makefile to build Embedthis GoAhead for linux
# NAME := goahead
VERSION := 4.1.
PROFILE ?= default
#ARCH ?= $(shell uname -m | sed 's/i.86/x86/;s/x86_64/x64/;s/arm.*/arm/;s/mips.*/mips/')
ARCH := arm
CC_ARCH ?= $(shell echo $(ARCH) | sed 's/x86/i686/;s/x64/x86_64/')
OS ?= linux
#CC ?= gcc
CC := arm-fsl-linux-gnueabi-gcc
CONFIG ?= $(OS)-$(ARCH)-$(PROFILE)
BUILD ?= build/$(CONFIG)
LBIN ?= $(BUILD)/bin
PATH := $(LBIN):$(PATH) ME_COM_COMPILER ?=
ME_COM_LIB ?=
ME_COM_MATRIXSSL ?=
ME_COM_MBEDTLS ?=
ME_COM_NANOSSL ?=
ME_COM_OPENSSL ?=
ME_COM_OSDEP ?=
ME_COM_SSL ?=
ME_COM_VXWORKS ?= ME_COM_OPENSSL_PATH ?= "/usr/local/openssl"
修改2:自定义代码的编译
在 goahead-linux-arm-default.mk 文件中添加对自定义程序 m283-webs 的编译支持
#
# m283-webs.o
#
DEPS_47 += $(BUILD)/inc/goahead.h
DEPS_47 += $(BUILD)/inc/js.h $(BUILD)/obj/m283-webs.o: \
m283-webs/m283-webs.c $(DEPS_47)
@echo ' [Compile] $(BUILD)/obj/m283-webs.o'
$(CC) -c -o $(BUILD)/obj/m283-webs.o $(CFLAGS) $(DFLAGS) -D_FILE_OFFSET_BITS= -D_FILE_OFFSET_BITS= -DMBEDTLS_USER_CONFIG_FILE=\"embedtls.h\" -DME_COM_OPENSSL_PATH=$(ME_COM_OPENSSL_PATH) $(IFLAGS) "-I$(ME_COM_OPENSSL_PATH)/include" m283-webs/m283-webs.c #
# m283-webs
#
DEPS_48 += $(BUILD)/bin/libgo.so
DEPS_48 += $(BUILD)/.install-certs-modified
DEPS_48 += $(BUILD)/obj/m283-webs.o ifeq ($(ME_COM_MBEDTLS),)
LIBS_48 += -lmbedtls
endif
ifeq ($(ME_COM_MBEDTLS),)
LIBS_48 += -lgoahead-mbedtls
endif
ifeq ($(ME_COM_MBEDTLS),)
LIBS_48 += -lmbedtls
endif
ifeq ($(ME_COM_OPENSSL),)
LIBS_48 += -lgoahead-openssl
endif
ifeq ($(ME_COM_OPENSSL),)
ifeq ($(ME_COM_SSL),)
LIBS_48 += -lssl
LIBPATHS_48 += -L"$(ME_COM_OPENSSL_PATH)"
endif
endif
ifeq ($(ME_COM_OPENSSL),)
LIBS_48 += -lcrypto
LIBPATHS_48 += -L"$(ME_COM_OPENSSL_PATH)"
endif
LIBS_48 += -lgo
ifeq ($(ME_COM_OPENSSL),)
LIBS_48 += -lgoahead-openssl
endif
ifeq ($(ME_COM_MBEDTLS),)
LIBS_48 += -lgoahead-mbedtls
endif $(BUILD)/bin/m283-webs: $(DEPS_48)
@echo ' [Link] $(BUILD)/bin/m283-webs'
$(CC) -o $(BUILD)/bin/m283-webs $(LDFLAGS) $(LIBPATHS) "$(BUILD)/obj/m283-webs.o" $(LIBPATHS_48) $(LIBS_48) $(LIBS_48) $(LIBS) $(LIBS)
2.编译与测试
复制 test.c 代码框架 到 m283-webs.c 来测试,后面按需修改
make -f projects/goahead-linux-arm-default.mk
在 build/linux-arm-default/bin 下生成了我们自定义程序的可执行文件 m283-webs ,将其拷贝到 nfs 的web调试目录
通过上节可知,web 运行需要包含的文件如下所示

在 web 中放入简单的 html 文件

在目标板测试 运行正常

GoAhead 常用操作实现
GoActions 过程(旧版本使用的是GoForms,使用方式基本相同),绑定C函数为具体的URL链接,主要用于用于响应用户输入,更新设置或执行特定动作。
一般过程:
1.通过 websDefineAction 函数注册GoAction 函数,即绑定该 C 函数到 /action/test
2.在 route.txt 中添加对应action路径
route uri=/action handler=action
3.在html 文件中的表单中触发 http POST操作指定URL /action/test
这样当html 表单触发post时就会调用注册好的 action函数 test
在新版本中,GoActions 过程的函数定义均可放在自定义程序中,下面是 m283-webs.c goaction过程的实现部分代码
m283-webs.c
MAIN(goahead, int argc, char **argv, char **envp)
{
char *argp, *home, *documents, *endpoints, *endpoint, *route, *auth, *tok, *lspec;
int argind, duration; #if WINDOWS
if (windowsInit() < ) {
return ;
}
#endif
route = "route.txt";
auth = "auth.txt";
duration = ; // 命令行解析
for (argind = ; argind < argc; argind++) {
argp = argv[argind];
if (*argp != '-') {
break; } else if (smatch(argp, "--auth") || smatch(argp, "-a")) {
if (argind >= argc) usage();
auth = argv[++argind]; #if ME_UNIX_LIKE && !MACOSX
} else if (smatch(argp, "--background") || smatch(argp, "-b")) {
websSetBackground();
#endif } else if (smatch(argp, "--debugger") || smatch(argp, "-d") || smatch(argp, "-D")) {
websSetDebug(); } else if (smatch(argp, "--duration")) {
if (argind >= argc) usage();
duration = atoi(argv[++argind]); } else if (smatch(argp, "--home")) {
if (argind >= argc) usage();
home = argv[++argind];
if (chdir(home) < ) {
error("Cannot change directory to %s", home);
exit(-);
}
} else if (smatch(argp, "--log") || smatch(argp, "-l")) {
if (argind >= argc) usage();
logSetPath(argv[++argind]); } else if (smatch(argp, "--verbose") || smatch(argp, "-v")) {
logSetPath("stdout:2"); } else if (smatch(argp, "--route") || smatch(argp, "-r")) {
route = argv[++argind]; } else if (smatch(argp, "--version") || smatch(argp, "-V")) {
printf("%s\n", ME_VERSION);
exit(); } else if (*argp == '-' && isdigit((uchar) argp[])) {
lspec = sfmt("stdout:%s", &argp[]);
logSetPath(lspec);
wfree(lspec); } else {
usage();
}
}
documents = ME_GOAHEAD_DOCUMENTS;
if (argc > argind) {
documents = argv[argind++];
}
initPlatform(); // 平台初始化,注册信号处理函数
if (websOpen(documents, route) < ) // 初始化服务器
{
error("Cannot initialize server. Exiting.");
return -;
}
#if ME_GOAHEAD_AUTH // 加载路径和鉴权配置文件
if (websLoad(auth) < )
{
error("Cannot load %s", auth);
return -;
}
#endif
logHeader(); // 打印web服务器基本信息
if (argind < argc) {
while (argind < argc) {
endpoint = argv[argind++]; // 参数中指定了服务器的endpoint 如./goahead -v ./web/ 192.168.10.111:80
// WEB端口监听
if (websListen(endpoint) < ) {
return -;
}
}
} else {
endpoints = sclone(ME_GOAHEAD_LISTEN);
for (endpoint = stok(endpoints, ", \t", &tok); endpoint; endpoint = stok(NULL, ", \t,", &tok)) {
#if !ME_COM_SSL
if (strstr(endpoint, "https")) continue;
#endif
if (websListen(endpoint) < ) {
wfree(endpoints);
return -;
}
}
wfree(endpoints);
} #if ME_ROM && KEEP // 采用web文件ROM化
/*
If not using a route/auth config files, then manually create the routes like this:
If custom matching is required, use websSetRouteMatch. If authentication is required, use websSetRouteAuth.
*/
websAddRoute("/", "file", );
#endif
#ifdef GOAHEAD_INIT
/*
Define your init function in main.me goahead.init, or
configure with DFLAGS=GOAHEAD_INIT=myInitFunction
*/
{
extern int GOAHEAD_INIT(); if (GOAHEAD_INIT() < ) {
exit();
}
}
#endif websDefineHandler("test", testHandler, , , ); // 定义一个请求处理程序
websAddRoute("/test", "test", );
#if ME_GOAHEAD_LEGACY
// 表示对 /goform 的请求都交给 websFormHandler 函数处理。函数的参数列表如下
websUrlHandlerDefine("/legacy/", , , legacyTest, ); // 设置form方式调用时候的文件位置
// websFormDefine(T("odbc_form_web_login"), odbc_form_web_login); // 定义form方式调用接口函数字符对应的函数名称
#endif
#if ME_GOAHEAD_JAVASCRIPT
websDefineJst("aspTest", aspTest); // 定义一个js本地函数
websDefineJst("bigTest", bigTest);
#endif
websDefineAction("test", actionTest); // goAction定义,在asp文件中调用C函数
websDefineAction("sessionTest", sessionTest);
websDefineAction("showTest", showTest); websDefineAction("led", on_led_set);
websDefineAction("buzzer", on_buzzer_set); #if ME_GOAHEAD_UPLOAD && !ME_ROM
websDefineAction("uploadTest", uploadTest);
#endif #if ME_UNIX_LIKE && !MACOSX
/*
Service events till terminated
*/
if (websGetBackground()) {
if (daemon(, ) < ) {
error("Cannot run as daemon");
return -;
}
}
#endif if (duration) {
printf("Running for %d secs\n", duration);
websStartEvent(duration * , (WebsEventProc) exitProc, );
}
websServiceEvents(&finished);
logmsg(, "Instructed to exit\n");
websClose(); #if WINDOWS
windowsClose();
#endif
return ;
} static void actionTest(Webs *wp)
{
cchar *name, *address; name = websGetVar(wp, "name", NULL);
address = websGetVar(wp, "address", NULL);
websSetStatus(wp, );
websWriteHeaders(wp, -, );
websWriteEndHeaders(wp);
websWrite(wp, "<html><body><h2>name: %s, address: %s</h2></body></html>\n", name, address);
websFlush(wp, );
websDone(wp);
} // led控制
static void on_led_set(Webs *wp)
{
// get the input value in query stream
char *io_val; io_val = websGetVar(wp, "val_led", NULL);
if(io_val)
system("echo 1 > /sys/class/leds/led-err/brightness");
else
system("echo 0 > /sys/class/leds/led-err/brightness");
} // 蜂鸣器控制
static void on_buzzer_set(Webs *wp)
{
char *io_val; io_val = websGetVar(wp, "val_buz", NULL);
if(io_val)
system("echo 1 > /sys/class/leds/beep/brightness");
else
system("echo 0 > /sys/class/leds/beep/brightness");
}
默认首页 index.html 添加 test 页面链接
<html><head><title>index.html</title></head>
<body>Hello /index.html</body>
<p>Link to reload <a href="index.html">this page</a></p>
<p>Link to <a href="/action/logout">log out</a></p>
<p>Link to <a href="test.html">test.html</a></p>
</html>
测试的网页 test.html
<!DOCTYPE html>
<html>
<head>
<title>test.html</title>
<meta charset="UTF-8">
</head>
<body>
<p>Please log in</p>
<form action=/action/test method="post">
<table>
<tr><td>账号:</td><td><input type="text" name="name"></td></tr>
<tr><td>密码:</td><td><input type="password" name="address"></td></tr>
<tr><td><input type="submit" name="submit" value="submit"></td>
<td><input type="reset" value="reset"></td></tr>
</table>
</form> <br />
<p align="left"><b> 蜂鸣器控制示例</p>
<form id="gpio-buzzer" action="/action/buzzer" method="post">
<input type="hidden" name="lab_buzzer" value="buzzer" />
<table>
<tr>
<td width=100>
BUZZER</td>
<td width=100>
<input type="checkbox" name="dir_buz" checked disabled title="out" />out</td>
<td width=100>
<input type="checkbox" name="val_buz" /></td>
<td width=100><input type="submit" value="set" /></td>
</tr>
</table>
</form> <br />
<p align="left"><b> LED控制示例</p>
<form id="gpio-led" action="/action/led" method="post">
<input type="hidden" name="lab_led" value="led" />
<table>
<tr>
<td width=100>
BUZZER</td>
<td width=100>
<input type="checkbox" name="dir_led" checked disabled title="out" />out</td>
<td width=100>
<input type="checkbox" name="val_led" /></td>
<td width=100><input type="submit" value="set" /></td>
</tr>
</table>
</form> <script type="text/javascript">
function loadXMLDoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","action/test",true);
xmlhttp.send();
}
</script> <div id="myDiv"><h2>需要刷新的局部内容</h2></div>
<button type="button" onclick="loadXMLDoc()">通过 AJAX 实现局部刷新</button> <p align="left"><b> © 2019 HTGD Co.,Ltd.</b> <a href="http://www.htgd.com.cn">公司主页</a></p>
</body>
</html>
每次重新编译之后,拷贝 m283-webs 可执行文件到测试nfs文件夹中
目标机 挂载nfs


运行 ./m283-webs -v /web/

在浏览器输入 192.168.1.124 点击test.html链接
或直接输入 192.168.1.124/test.html

显示效果

测试 goaction 交互
填写内容 点击 submit,web 返回正常

指示灯、蜂鸣器等web操作目标板硬件,测试正常;
至此完成了 web 的部分内容交互,但该交互的页面刷新时整个页面的刷新,非常不方便;
下一节实现部分页面刷新数据交互 Embedded Javascript,在网页上为 Ajax 技术。
GoAhead4.1.0 开发总结二(自定义使用)的更多相关文章
- GoAhead4.1.0 开发总结一(移植)
环境 官方文档:https://www.embedthis.com/goahead/doc/ 源码下载: goahead-4.1.0-src.tgz 系统平台:Ubuntu 12.04.4 gcc v ...
- GoAhead4.1.0 开发总结三(GoAction+Ajax实现局部数据交互)
环境 官方文档:https://www.embedthis.com/goahead/doc/ 源码下载: goahead-4.1.0-src.tgz 系统平台:Ubuntu 12.04.4 gcc v ...
- MS CRM 2011的自定义和开发(11)——插件(plugin)开发(二)
http://www.cnblogs.com/StoneGarden/archive/2012/02/06/2339490.html MS CRM 2011的自定义和开发(11)——插件(plugin ...
- [开源地址] 放弃Flink,.NET5.0开发CSharpFlink,简要设计、部署及二次开发说明。
github地址:https://github.com/wxzz/CSharpFlinkgitee地址:https://gitee.com/wxzz/CSharpFlink 1 概述及背景 我们有一个 ...
- 用函数式编程,从0开发3D引擎和编辑器(二):函数式编程准备
大家好,本文介绍了本系列涉及到的函数式编程的主要知识点,为正式开发做好了准备. 函数式编程的优点 1.粒度小 相比面向对象编程以类为单位,函数式编程以函数为单位,粒度更小. 正所谓: 我只想要一个香蕉 ...
- 从0开发3D引擎(二):准备预备知识
大家好,本文介绍了开发3D引擎需要的预备知识,给出了相关的资源. 上一篇博文 从0开发3D引擎(一):开篇 了解Web 3D Web 3D的历史 目前Web 3D是基于WebGL这个Web端3D AP ...
- 从0开发3D引擎(十二):使用领域驱动设计,从最小3D程序中提炼引擎(第三部分)
目录 上一篇博文 继续实现 实现"DirectorJsAPI.init" 实现"保存WebGL上下文"限界上下文 实现"初始化所有Shader&quo ...
- Github团队开发示例(二)
Github团队开发示例(二) 作者:Grey 原文地址:http://www.cnblogs.com/greyzeng/p/6063765.html 接之前讲的Github团队开发示例(一),本文主 ...
- 【百度地图开发之二】基于Fragment的地图框架的使用
写在前面的话: [百度地图开发之二]基于Fragment的地图框架的使用(博客地址:http://blog.csdn.net/developer_jiangqq),转载请注明. Author:hmji ...
随机推荐
- JavaEE JDBC 读写LOB大对象
JDBC 读写LOB大对象 @author ixenos LOB 除了数字.字符串和日期之外,许多数据库还可以存储大对象,例如图片或其他数据, 在SQL中,二进制(字节型)大对象称为BLOB,字符型大 ...
- POJ 3264 RMQ问题 用dp解决
#include <cstdio> #include <cstring> #include <iostream> using namespace std; ; #d ...
- [luoguP1082] 同余方程(扩展欧几里得)
传送门 ax≡1(mod b) 这个式子就是 a * x % b == 1 % b 相当于 a * x - b * y == 1 只有当 gcd(a,b) == 1 时才有解,也就是说 ax + by ...
- [bzoj1500][NOI2005]维修数列[Treap][可持久化Treap]
非旋转式Treap1500 :) #include <bits/stdc++.h> #pragma GCC optimize(3) using namespace std; const i ...
- poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)
http://poj.org/problem?id=3041 在n*n的网格中有K颗小行星,小行星i的位置是(Ri,Ci),现在有一个强有力的武器能够用一发光速将一整行或一整列的小行星轰为灰烬,想要利 ...
- Organize Your Train part II 字典树(此题专卡STL)
Organize Your Train part II Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8787 Acce ...
- 【.Net 学习系列】-- .Net 指定时间段内定时执行的Windows服务(System.Threading.Thread)
创建一个Windows服务项目:解决方案(右击)——> 添加 ——> 新建项目——>项目类型选择Windows——>模板选择Windows服务 ,如图: 编写Windows服务 ...
- 图解Windows下安装WebLogic
Oracle 的Weblogic分开发者版本和生产版本,有32位和64位.一般生产版本的weblogic是64位的,安装文件是一个大小为1G多的jar包.去oracle官网上下载64版weblogic ...
- linux程序命令行选项的3种风格:unix、gnu、x toolkit
In Unix-like systems, the ASCII hyphen-minus is commonly used to specify options. The character is u ...
- AE After Effect 如何替换和修改素材
替换素材:如图所示,相框外的人是成双成对的,相框里面的却只有一个人,我们想要把这个素材替换成两个人的.我们鼠标放到视频预览框的任何一个元素上面底部都会提示这是什么素材.比如我放到一个人的上面,则该人物 ...