web网页程序修改

打开gStudio之后,点击菜单栏中Help->Contents。先把这个诡异的编程语言看一遍吧。这里搬一些东西出来。

GoDB简介

从第一副图片中,我们可以看出,从源文件到可执行文件的过程。

从第二幅图我们可以了解到GoDB是如何跨平台的。

编程语言的话:

GBasic is a variant of the Basic Language included in GoDB platform as the scripting language.

这种编程语言大小写不区分,真是编程界的一朵奇葩。

GBasic编程语言

GBasic程序通常是有一个frm文件和与之名字相同的bas文件。比如说当HOME.frm被加载时,HOME.bas就会被执行。

  • GBasic中的字符串变量名以$结尾。
  • 如果没有$的变量则认为是数值变量
  • GBasic有两种对象(object),一种是Form Field Objects(可理解为Visual Studio中的rc文件),另外一种是数据库(专业版才能使用)
  • 在GBasic中调用From对象方式是用#对象名
  • GBasic中有三种变量范围,全局,局部和当前页面。

    其中变量名以开头的是全局变量,你可以在工程的任何地方访问这个变量。没有以开头的变量并且声明在Sub或者Function之外的,则为页面变量,声明在Sub或者Function内部的则是局部变量。
  • 像其它任何语言一样,GBasic也可以将针对多行代码进行封装。GBasic提供Subroutines和Functions这两种方式,前者没有返回值,后者需要返回值。如果要直接调用Subroutines,你需要在其前面家call,比如说call subname,而Functions的调用则不用。
  • Functions返回值的做法是赋值给函数名。

GBasic自带了很多封装好的函数,这些函数如何用,请看Help。

GStudio这个IDE像Visual Stduio一样,支持控件的事件触发(按钮按下,编辑框改变etc.)这些事件称之为控件的事件,还有另外一种事件叫做Global Event

具体查看Help中的GBasic Reference->Global Event。这里稍微介绍下

form_load当frm文件加载首先执行的是这个Sub。

form_notify当收到服务器反馈时自动调用,此时在用GetMessage获取消息内容..

form_timer,定时器触发时调用此Sub,通常使用settimer(1000)来使能定时触发。

所以一般阅读GoDB工程代码一般先从每个bas文件的form_load开始看起。

Debug

  • 在GUI的下拉菜单中,保证当前选中的是"DEBUG"模式;
  • 按F7编译工程,按F5会编译和启动项目;
  • 保证你在"Win32_Debug"文件夹中有"ip.txt"文件,这个是用于用户登录的。

Release

  • Debug/ Release下拉菜单中选中Release
  • 在View-option在选项卡Build中在Make Read-Only BDB选中
  • 在文件夹Win32_Release中找到gIPNC-ro.bdb
  • 使用以下命令生成gIPNC-ro.gz

gIPNC工程分析

我们做的是在原有基础上添加东西,修修补补,谁要是有精力就从头开始弄吧。

bas和frm和inc一一对应,bas为执行文件,inc为头文件,frm为form文件,相当于Visual Studio中的rc文件。

还是先分析流程吧。

首先当然是登录界面,那就是对应logon.bas和auth.bas,首次登录执行的auth.bas文件,而用户刷新过程中执行的logon.bas文件。

关于logon.bas

readprofile("PAGENAME",pageName$)
...
readprofile("IPNC",loginDet$)
...

首先读取变量名为IPNC和PAGENAME的profile,如果读取得到那么就将读取到的用户名和密码填充到用户名编辑框和登录编辑框(这就是记住密码功能),调用dwnldIniFile函数进行Http请求,请求内容是ip地址/ini.htm,这样如果认证通过,那么此时已经把所有关键字及其内容保存到~responseData$全局环境变量上。获取失败则弹出用户或密码错误。读取profile错误,则加载auth.frm。

我们知道,TI IPNC除了用户验证登录之外还有区分用户权限,所以在成功调用dwnldIniFile调用getUserAuthority获取当前用户的权限,获取失败弹出错误信息,成功并且PAGENAME的值为LOGIN则加载auth.frm,否则直接进入liveVideo.frm

温馨提示,仔细研究下writeprofile函数,你就知道如何做到真正的记住密码。

温馨提示,GetIPAddress()是进行调试的关键。

分析auth.bas不难发现,无非就是。先将读取到的IPNC变量的值进行填充,然后这个文件主要的逻辑就是cmdSubmit_Click这个按钮按下的事件处理函数了。先进行输入验证,然后是登录验证,也是调用dwnldIniFile进行认证getUserAuthority。最后成功加载livevideo.frm,并写PAGENAME的profile。

** 几个比较关键的文件 **

这个工程里面有几个文件是比较重要(特殊的文件)的那就是leftmenu.bas,functions.inc,defines.inc,common.inckeywords.inc

  1. 其中leftmenu.bas是网页侧边栏的执行文件,添加,删除子菜单就修改这个文件。
  2. functions.inc里面定义了众多函数,大部分是网页keyword获取和设置的函数。
  3. defines.inc文件定义了一些关键数字,比如说侧栏菜单(主菜单,子菜单)多少个,比如关键字最多有多少个,有时候一些莫名其妙的错误就是由于这个文件上的数字没对上引起的。
  4. common.inc定义了一些通用函数,比如编辑框可以输入哪些字符,不可以输入哪些字符(CheckKey),产生Request Header(generateauthHeader)。
  5. keywords.inc,这个仅在functions.inc中被包括。这个文件其实不太重要,作用仅仅是用于显示获取或设置关键字时的错误信息而已。

logon.bas和auth.bas他们都包括了functions.inc,defines.inc,common.inc。而其它的主页面除了这个三个文件之外,还包括leftmenu.bas,这样的效果就是将侧边栏和各个form的网页叠加起来。

GBasic是从头到尾顺序执行的,所以每个bas文件先执行Sub或者functions之外的语句之后,然后再执行form_load事件,由于先包括了leftmenu.bas,所以会先执行leftmenu.bas里面的内容,而每个frm页面都包括了leftmenu.frm文件。这样就加载了侧边栏。

leftmenu负责触发加载各个页面。

添加删除侧边栏菜单

这里只说怎么加,不讨论怎么建页面。

打开leftmenu.bas

dims ~menuArray$(MAXMAINMENU+MAXSUBMENU+3)
dims menuOffImg$(MAXMAINMENU) = ("!camera_Off.bin","!users_Off.bin","!settings_Off.bin","!maintanance_off.bin","!support_off.bin")
dims ~menuOnImg$(MAXMAINMENU) = ("!camera_On.bin","!users_On.bin","!settings_On.bin","!maintanance_on.bin","!support_on.bin")
dims ~urlMainArray$(MAXMAINMENU) = ("!liveVideo.frm", "!addusers.frm","!videoImageSettings.frm","!maintenance.frm","!supportScreen.frm")
dims ~urlSubArray$(MAXSUBMENU) = ("!videoImageSettings.frm","!videoAnalyticsSetting.frm","!DMVAeventMonitor.frm","!display_settings.frm", "!audioSetting.frm","!setDateTime.frm", "!NetworkSettings.frm", "!alarmSettings.frm", "!class.frm","!storageSetting.frm") dimi dmvaEnable #imgselected.hidden = 1
loadMenuCaptions()
....

上面是我修改过的。其中比较关键的是几个宏定义的定义,如果你要修改,请算好侧边栏的个数,然后修改在defines.inc中的数值。bin文件是主菜单的对应的图片,关于图片后面才说,frm就是对应的页面啦,算好顺序...

  1. 如果要增加页面,则在leftmenu.frm中增加一个ReadOnly控件,然后NAME必须为rosubmenu,value为空,背景那些参照已有的..你会发现有好几个ReadOnly都叫做rosubmenu,然后这个ide就自动就其他们的name改为类似数组的样子..rosubmenu[0],而程序里面也是如此引用。
  2. 修改字符串数组~URLsUBaRRAY$,将建立好的FRM的文件名添加到末尾
  3. 修改子菜单数量maxsubmenu和leftmenuctrls(在DEFINE.INC中定义).各加1
  4. 修改子菜单名字,修改MENUcAPTIONS.LAN文件,这个文件前面5个是主菜单,后面是子菜单的名字
  5. BUG.将ARRmOUSEpOS(14, 4)改成ARRmOUSEpOS(maxmainmenu+maxsubmenu, 4),否则会出现数组越界
  6. 子菜单对应的页面的BAS文件必须包括两个函数savepage()和chkValueMismatch(),否则会报错..

当然leftmenu大部分菜单鼠标点击时鼠标的触发事件,也就是加载相应的页面。当然还有什么图标排列,音视频开关等处理...

另外值得注意的是:子菜单中有可能有一两个页面是默认隐藏的,某种条件触发下才显示。比如Live Video页面那个Example的下拉框就是一个触发条件,另外如果用户权限不同,子菜单显示的个数也有所不同,这些逻辑都在leftmenu.bas中。

子页面流程分析

IPNC网页默认几个页面,大部分都是传统的表单页面,无非就是些CheckBoxEditCommonBox之类的控件,加载页面的时候,就是获取服务器上对应的控件的值然后填充进去,保存页面的时候,则是发送http请求到web服务器进行保存然后重新获取更新。

一般来说一个控件对应一个关键字。

我们先从对应页面的form_load看起,然后看savepage,然后看各个控件触发事件..其它全局事件。

我们拿声音设置页面为例,对应的文件是audiosetting.basaudiosetting.frm文件。

Sub Form_Load
dimi retVal
retVal = loadIniValues() if ~maxPropIndex = 0 then
msgbox("无法加载初始配置",0,"错误",3)
loadurl("!auth.frm")
endif call displayControls(LabelName$,XPos,YPos,Wdh,height)
call loadInitialValues() showSubMenu(0,1)
setfocus("rosubmenu[4]")
selectSubMenu()
setfocus("chkenableaudio")
call chkenableAudio_Click 'TR-19 getimagefile(sliderImage$,"!slider_but.jpg")
#lblsuccessmessage$ = "" 'TR-35 End Sub

retVal = loadIniValues()

这是个关键函数,这个函数里面请求http://ip/ini.htm获取所有关键字的值,如果获取失败了,就提示错误。在loadIniValues函数中,有个字符串数组非常关键,每次添加新的关键字都必须修改这个字符串在后面添加新的关键字。keywords$

网页在functions.inc中的loadIniValues()中解析得到这些值将这些属性和对应的放分别放到字符串数组~iniProperties$和iniPropValues$中.

值得注意的是在放入~iniProperties$之前,在每个属性名之前加了字母"g".

每个页面的form_load都会在一开始调用这个函数

call loadInitialValues()

这个函数,也是非常典型,几乎每个页面都会做类似的处理(可能函数名字不同或者没用函数),作用是获取当前页面关键字的值然后填充到控件里面。

然后这里基本上都用到functions.inc中"get"开头的一些函数,这些函数参数不同,都是处理流程一致,都是分析~iniPropValues$这个全局变量然后取出对应的关键字的值。

retVal = getAudioSetting(enableAudio,audioMode,inputVolume,_
encoding,sampleRate,bitRate, _
alarmLevel,outputVolume)
'functions.inc中定义
function getAudioSetting(byref dimi enableAudio, byref dimi audioMode, byref dimi inputVolume, _
byref dimi encoding, byref dimi sampleRate, byref dimi bitRate, _
byref dimi alarmLevel, byref dimi outputVolume)
'TR-26
dims varName$(8) = ("enableAudio","audioMode","inputVolume", _
"encoding","sampleRate","bitRate", _
"alarmLevel","outputVolume") dims propName$(8) = ("gaudioenable","gaudiomode","gaudioinvolume", _
"gencoding","gsamplerate","gaudiobitrate", _
"galarmlevel","gaudiooutvolume") dims tempVal$(8)
dimi i,retVal retVal = getiniValues(propName$,tempVal$) if retVal = 0 then for i= 0 to ubound(tempVal$) {varName$(i)} = strtoint(tempVal$(i)) next endif return retVal End Function

所以当你添加新的关键字时,做法可以是在原有函数基础增加参数。也可以按照里面的这些函数的形式和逻辑重新定义一个新的函数...

下面介绍另外一个重要函数,那就是savepage函数,记住不管你页面是否需要保存,都必须存在这个函数。正如前面一小节所说......

savepage函数里面重要是使用functions.inc中"set"开头的一些函数。这些函数参数不尽相同,但是逻辑相同,都是通过发送http请求设置关键字的值。

savepage函数一般还会做控件输入值有效的检测,错误成功信息显示等处理...

/*一般实在保存按钮的事件响应函数中调用savepage函数*/
Sub cmdsave_Click
if canReload = 1 then
savePage()
end if
End Sub
Sub savePage()
'Validate user input controls values
iff validatemodecontrols() = 0 then return dimi retVal,i
' TR-26 set values to camera
retVal = setAudioSetting(#chkenableaudio,#drpaudiomode,atol(#sldaudioinput$),_
#drpencoding,#drpsamplerate,#drpbitrate,_
#sldalarmlevel,atol(#sldaudiooutput$)) saveSuccess = retVal
tempX = #lblsuccessmessage.x
'Based on reload flag wait for the camera to restart
if getReloadFlag() = 1 then 'TR-45
#lblsuccessmessage.style = 128
#lblsuccessmessage.x = #lblsuccessmessage.x + #lblsuccessmessage.w/3
canReload = 0
animateCount = 1
call animateLabel("lblsuccessmessage","参数更新中")
else // If Reload animation is not required
canReload = 1
end if if canReload = 1 Then //Do the remaining actions after reload animation is done
call displaySaveStatus(saveSuccess)
end if
End Sub
function setAudioSetting(dimi enableAudio, dimi audioMode, dimi inputVolume, _
dimi encoding, dimi sampleRate, dimi bitRate, _
dimi alarmLevel, dimi outputVolume)
dimi ret
dims value$
dims responseData$
' TR-26
value$ = "audioenable="+enableAudio+"&audiomode="+audioMode+"&audioinvolume="+inputVolume+_
"&encoding="+encoding+"&samplerate="+sampleRate+"&audiobitrate="+bitRate+_
"&alarmlevel="+alarmLevel+"&audiooutvolume="+outputVolume
pprint value$
ret = setProperties(value$, responseData$) if ret > 0 then dims propName$(8) = ("gaudioenable","gaudiomode","gaudioinvolume", _
"gencoding","gsamplerate","gaudiobitrate", _
"galarmlevel","gaudiooutvolume")
dims propVal$(8) propVal$(0) = enableAudio
propVal$(1) = audioMode
propVal$(2) = inputVolume
propVal$(3) = encoding
propVal$(4) = sampleRate
propVal$(5) = bitRate
propVal$(6) = alarmLevel
propVal$(7) = outputVolume ~errorKeywords$ = ""
~errorKeywords$ = chkRetStatusAndUpdate$(responseData$,propName$,propVal$) if len(~errorKeywords$) > 0 then
return -10
else
return ret
endif endif return ret End Function

跟踪到里面去,不难发现,实际上就是发送这样形式的Http请求:

vb.htm?keyword1=xx&keyword2=xxx

当增加新的关键字时,可以仿照这些set开头函数重新定义一个新的函数,也可以在原有基础上扩充。

GoDB端添加关键字的流程

这里介绍在GoDB端添加关键字的流程。我们忽略boa端代码的修改,所以修改完之后,既不能获取到这个关键字也无法设置成功。

现在举添加rtmp功能的例子..

页面如下,在网络/端口设置页面添加一个checkbox和一个edit,这就对应了两个关键字,关键字名字分别为rtmp_enrtmp_url(随意)

还是从from_load开始,还是从加载控件默认值的函数开始...

call ShowDefaultValues()

在这个Sub内:

dimi rtmp_en

Dims rtmp_url$

然后我们选择扩充已有的函数

retVal=getSNTPRTSPDetails(sntpServer$, multiCast,rtmp_en,rtmp_url$)

/*在functions.inc中定义*/
function getSNTPRTSPDetails(byref dims sntpServer$,byref dimi multiCast,byref dimi rtmp_en,byref dims rtmp_url$) dims varName$(4) = ("sntpServer$","multiCast","rtmp_en","rtmp_url$")
dims propName$(4) = ("gsntpip","gmulticast","grtmp_en","grtmp_url")
dims tempVal$(4)
dimi i,ret
ret=getiniValues(propName$,tempVal$) if ret>=0 then
for i= 0 to ubound(tempVal$)
if i=1 or i=2 then
{varName$(i)} = strtoint(tempVal$(i))
else
{varName$(i)} = tempVal$(i)
endif next
endif
return ret End Function

你对比下原始函数就知道我修改了哪里..

接着我们修改functions.inc中的loadIniValues函数,将rtmp_enrtmp_url添加到keywords$字符串后面

/*....*/
keywords$ +=",aviformat,aviformatname,aviduration,avidurationname,reloadtime,qpinit1,qpinit2,qpinit3"_
",videocodeccombo,videocodeccomboname,streamname1,streamname2,streamname3"_
",localdisplayname,sdinsert,reloadflag,dmvaenable,minnamelen,maxnamelen,minpwdlen,maxpwdlen,maxaccount"_
",bkupfirmware,display_mode,ppt_sw_en,ppt_sw_sensitivity,ppt_sw_interval_time,channel_id,psname,piname,ch_id_name"_
",file_size,video_long,brightness2,contrast2,saturation2,sharpness2,brightness3,contrast3,saturation3,sharpness3,brightness4,contrast4,saturation4,sharpness4"_
",language,ftp_upload_option,ftp_upload_time,trackip,cloudip,serverenable,singlecodecres,rtmp_en,rtmp_url"

接着我们修改keywords.inc文件,将这两个关键字添加到cameraKeywords$关键字后面。"|"右面是错误提示信息,合理填写即可。

cameraKeywords$ += ",display_mode|Display mode,ppt_sw_en|PPT Switch Enable,ppt_sw_interval_time|PPT Switch interval Time,"_
",ppt_sw_sensitivity|PPT Switch sensitivity,channel_id|main display channel,language|language,trackip|track ip,cloudip|cloudip,"_
",serverenable|Upload to server,singlecodecres|resolution for single stream,rtmp_en|rtmp enable,rtmp_url|rtmp url"

接着,我们修改savepage函数。

retVal = setSNTPRTSPDetails(#txtsntpserver$, #chkrtspmulticast,#chkrtmp,#txtrtmpurl$)

这里传入的参数是直接将对象的值传入..

function setSNTPRTSPDetails(dims sntpServer$,dimi multiCast,dimi rtmp_en,dims rtmp_url$)
dimi ret
dims SNTPRTSPDetails$
dims responseData$ SNTPRTSPDetails$="sntpip="+sntpServer$+"&multicast="+multiCast+"&rtmp_en="+rtmp_en+"&rtmp_url="+rtmp_url$ ret = setProperties(SNTPRTSPDetails$, responseData$) if ret >= 0 then dims propName$(4) = ("gsntpip","gmulticast","grtmp_en","grtmp_url") dims propVal$(4)
propVal$(0) = sntpServer$
propVal$(1) = multiCast
propVal$(2) = rtmp_en
propVal$(3) = rtmp_url$ ~errorKeywords$ = ""
~errorKeywords$ = chkRetStatusAndUpdate$(responseData$,propName$,propVal$) if len(~errorKeywords$) > 0 then
return -10
else
return ret
endif endif return ret End Function

这样着,关键字添加完毕了,按照前面文章说的步骤编译生成吧..

boa端添加关键字的流程

只讲怎么添加。

请自行用工具定位下面变量,函数的位置。

先从SysInfo结构体开始修改,这个结构体将保存所有网页表单,关键字的值。

我们在末尾添加

typedef struct SysInfo{
//....
__u8 rtmp_enable; ///< rtmp_enable
char rtmp_url[MAX_RTMP_URL_LEN+1];
}SysInfo;

网页需要出厂默认值,所以在修改system_default.h文件添加两个宏定义。

#define RTMP_EANABLE_DEFAULT 0 //RTMP使能,0为不使能...
#define RTMP_URL_DEFAULT "rtmp://192.168.1.120:1935/live/xxoo"

修改file_mng.c

修改全局静态结构体SysInfoDefault,往末尾添加

static SysInfo SysInfoDefault =
{
//....
RTMP_EANABLE_DEFAULT,
RTMP_URL_DEFAULT
};

修改HttpOptionTable结构体。

HTTP_OPTION HttpOptionTable [] =
{
//....
{ "rtmp_en" , set_rtmp_en , AUTHORITY_OPERATOR, FALSE, TRUE, NULL },
{ "rtmp_url" , set_rtmp_url , AUTHORITY_OPERATOR, FALSE, TRUE, NULL },
//...
}

接着在该表所在文件定义这两个函数,一个是整数,一个字符串,注意区别。

void set_rtmp_en(request *req, COMMAND_ARGUMENT *argm)
{
__u8 value = atoi(argm->value); do {
ControlSystemData(SFIELD_SET_RTMP_EN, (void *)&value, sizeof(value));
req->buffer_end += sprintf(req_bufptr(req), OPTION_OK "%s\n", argm->name);
return;
} while (0);
req->buffer_end += sprintf(req_bufptr(req), OPTION_NG "%s\n", argm->name);
} void set_rtmp_url(request *req, COMMAND_ARGUMENT *argm)
{
do {
if(ControlSystemData(SFIELD_SET_RTMP_URL, (void*)argm->value, strlen(argm->value)) < 0)
break;
req->buffer_end += sprintf(req_bufptr(req), OPTION_OK "%s\n", argm->name);
return;
} while (0);
req->buffer_end += sprintf(req_bufptr(req), OPTION_NG "%s\n", argm->name);
}

sysctrl.h定义SFIELD_SET_RTMP_EN和SFIELD_SET_RTMP_URL

ControlSystemData函数中添加

		case SFIELD_SET_RTMP_URL:
ret = SetSysCommon(data, len,SYS_MSG_SET_RTMP_URL);
break; case SFIELD_SET_RTMP_EN:
ret = SetSysCommon(data, len, SYS_MSG_SET_RTMP_EN);
break;

Msg_Def.h中定义SYS_MSG_SET_RTMP_URLSYS_MSG_SET_RTMP_EN

ProcSysMsg函数添加

		case SYS_MSG_SET_RTMP_EN:
{
unsigned char value;
DBG("SYS_MSG_SET_RTMP_EN\n");
if(pMsg->length != sizeof(value))
break;
ShareMemRead(pMsg->offset, &value, pMsg->length);
if(SetRtmpEn(value) != 0){
printf("\nSystemServer:Fail at SYS_MSG_SET_MULTICAST\n");
break;
}
ret = 1;
break;
} case SYS_MSG_SET_RTMP_URL:
{
if(pMsg->length > SYSTEM_SERVER_BUFFER_LENGTH){
printf("String length bigger then System Server Buffer\n");
break;
}
ShareMemRead(pMsg->offset, buffer, pMsg->length);
if(SetRtmpUrl(buffer, pMsg->length) != 0){
printf("Fail at SYS_MSG_SET_RTMP_URL\n");
break;
}
ret = 1;
break;
}

定义SetRtmpUrlSetRtmpEn函数(这里在system_control.c中定义)

这两个函数的内容就非常自由了,不过和其它相同的地方就是就是需要将关键字保存到sysenv.cfg文件中。

所以分别各自定义一个函数用于保存关键字。

fSetRtmpEnfSetRtmpUrl(file_msg_drv.c)中定义。

int fSetRtmpEn(unsigned char value)
{
SysInfo *pSysInfo = (SysInfo *)pShareMem;
if(pSysInfo == NULL)
return -1;
if (value == pSysInfo->rtmp_enable)
return 0;
memcpy(&pSysInfo->rtmp_enable, &value, sizeof(value));
return SetSysInfo(0);
}
int fSetRtmpUrl(void *buf, int len)
{
SysInfo *pSysInfo = (SysInfo *)pShareMem;
if(pSysInfo == NULL)
return -1;
if(sizeof(pSysInfo->rtmp_url) < len + 1)
return -1;
memcpy(&pSysInfo->rtmp_url, (char*)buf, len);
pSysInfo->rtmp_url[len] = '\0';
return SetSysInfo(0);
}

int SetRtmpEn(unsigned char value)
{
int ret = 0;
SysInfo *pSysInfo = GetSysInfo();
if(pSysInfo == NULL)
return -1;
if(value != pSysInfo->rtmp_enable)
{
ret = fSetRtmpEn(value);
if ( value == 1 )
rtmp_start();
else
rtmp_stop(); }
return ret;
}

int SetRtmpUrl(void * buf, int length)
{
int ret = 0;
signed char* serverip=(signed char*)buf;
SysInfo *pSysInfo = GetSysInfo();
if(pSysInfo == NULL)
return -1;
if(strncmp(serverip,pSysInfo->rtmp_url,length) != 0)
{
ret = fSetRtmpUrl(buf,length);
rtmp_stop();
if ( pSysInfo->rtmp_enable )
rtmp_start();
}
return ret;
}

修改HttpArgument结构体,用于获取关键字的值

HTML_ARGUMENT HttpArgument [] =
{
//...
{ "rtmp_en" , para_rtmp_en , AUTHORITY_VIEWER , NULL },
{ "rtmp_url" , para_rtmp_url , AUTHORITY_VIEWER , NULL },
//...
};

int para_rtmp_en(char *data, char *arg)
{
SysInfo* pSysInfo = GetSysInfo();
if(pSysInfo == NULL)
return -1;
return sprintf(data, "%d", pSysInfo->rtmp_enable);
} int para_rtmp_url(char *data, char *arg)
{
SysInfo* pSysInfo = GetSysInfo(); if(pSysInfo == NULL)
return -1;
return sprintf(data, "%s", pSysInfo->rtmp_url);
}

以上就成功的加入了关键字了,在其它线程里面,你只需要调用

    SysInfo *pSysInfo = GetSysInfo();
//pSysInfo->rtmp_en
//pSysInfo->rtmp_url

TI IPNC Web网页之网页修改教程的更多相关文章

  1. TI IPNC Web网页之流程分析

    流程 Appro IPNC使用的web服务器是boa. 请仔细理解下面这段话. boa这个web服务器是GUI界面和IPNC应用程序之间的通信的桥梁.它的责任是从web GUI中接收HTTP请求,并且 ...

  2. Ti IPNC Web网页之ActiveX控件

    Ti IPNC Web网页之ActiveX控件 本篇介绍关于TI IPNC网页中播放器相关的东西. gStudio工程中添加播放器并控制播放器 打开IPNC网页时首先会自动下载ActiveX控件并安装 ...

  3. TI IPNC Web网页之GoDB开发环境

    介绍 下面介绍DM8127/DM385 IPNC RDK中网页制作相关的东东. 具体来说,各位获得这个RDK包时有以下文件: IPNC_RDK_DM812x_DM385_Version3.5.0.ta ...

  4. TI IPNC Web网页之进阶修改

    GoDB内嵌HTML 原始的页面里面已经有一个内嵌HTML的例子了,那就是维护支持页面.下图是稍微修改后的页面...请自行脑补. 这里使用的是上一节所说的gdo containter的方法. 打开ma ...

  5. 网页图表Highcharts实践教程之外层图表区

    网页图表Highcharts实践教程之外层图表区 Highcharts图表区 图表区是图表的基本区域.所有的数据和图形都是绘制在图表区中.从图形绘制范围来分,图表区域分为外层图表区和绘图区.本章将详细 ...

  6. 网页图表Highcharts实践教程之图表代码构成

    网页图表Highcharts实践教程之图表代码构成 Highcharts第一个实例 下面我们来实现本书的第一个Highcharts实例. [实例1-1]下面来制作北京连续一周最高温度折线图.操作过程如 ...

  7. 网页图表Highcharts实践教程之标签组与载入动画

    网页图表Highcharts实践教程之标签组与载入动画 Highcharts标签组 在图表的大部分元素都提供了标签功能.但很多时候,我们需要额外说明一些信息.这个时候借助原有的图表元素的标签功能就不是 ...

  8. 网页图表Highcharts实践教程标之添加题副标题版权信息

    网页图表Highcharts实践教程标之添加题副标题版权信息 Highcharts辅助元素 辅助元素图表的非必要元素,如标题.版权信息.标签.载入动态.它们不和图表数据发生关联,只是额外说明一些基本信 ...

  9. 网页图表Highcharts实践教程之图表区

    网页图表Highcharts实践教程之图表区 网页图表Highcharts图表区 图表区是图表的基本区域.所有的数据和图形都是绘制在图表区中.从图形绘制范围来分,图表区域分为外层图表区和绘图区.本章将 ...

随机推荐

  1. 【转】安装Vue.js的方法

    安装vue.js的方法   一.简介 Vue.js 是什么 Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量 ...

  2. 20145103《JAVA程序设计》第十周学习总结

    网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就是狭义的网络编程范畴.在发送和接收数据时,大部分的程序设 ...

  3. Nginx解决post请求405问题

    和工商银行的一个合作项目,对方客户端需要请求我们的一个静态页面,但是客户端发送过来的请求方法用的post,日志显示405错误(请求方法错误),正常一个静态页面直接用get请求就可以了,工行那边说写死了 ...

  4. 爬虫之Xpath案例

    案例:使用XPath的爬虫 现在我们用XPath来做一个简单的爬虫,我们尝试爬取某个贴吧里的所有帖子,并且将该这个帖子里每个楼层发布的图片下载到本地. # tieba_xpath.py #!/usr/ ...

  5. LeetCode——Longest Palindromic Subsequence

    1. Question Given a string s, find the longest palindromic subsequence's length in s. You may assume ...

  6. 51Nod 1433 0和5(9的倍数理论)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1433 思路: 数论中关于9的倍数的理论:若是一个数能被9整除,则各位数之 ...

  7. .net 获取浏览器Cookie(包括HttpOnly)

    网上好不容易找到的,分享+收藏 一.接口文件 using System; using System.ComponentModel; using System.Net; using System.Run ...

  8. mac terminal update management pack

    npm -g outdated npm -g install npm@6.4.1

  9. Quartz(自动任务)中的触发器Trigger

    1.Quartz中的触发器TriggerJob 包含了要执行任务的逻辑,但是 Job 对何时该执行却一无所知.这个事情留给了 Trigger.Quartz Trigger 继承了抽象的 org.qua ...

  10. 【Python】模块学习之(__call__)实现准确计算函数运行时间

    背景 博主在写自动化的过程中,有遇到有的用例运行缓慢的问题,想起在上一家公司的的“自动化工厂”有一个指标:两小时内运行完所有的用例才算合格.所以想计算每一个用例的运行时间. 思路 因为使用的POM模型 ...