自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

辛佳雨的专栏

我的思想,凭空游弋

  • 博客(238)
  • 资源 (604)
  • 收藏
  • 关注

原创 外部系统不连设备,只订阅 /message 开头的十四个主题

十四个主题、一个信封、一个写出口,构成了 SagooIoT 的北向事件面;那十个 controller 构成了按需拉取的一面。两者加起来,第三方系统接入时只需要做三件事:订阅/message/#、按messageId去重、需要写操作时用 AK/SK 签名调 HTTP。设备侧那些协议细节——Modbus 的字节序、网关的批量帧、属性值的类型转换——全部留在平台内部。对接方理解成本越低,平台被替换的成本就越高。

2026-11-05 07:34:18 228

原创 网关下面挂了三十台设备,平台只看到一条连接

回头看开头那两个数字:Broker 的 1 和平台的 31。差的 30 不是"没连上的设备",而是"不需要自己连的设备"。把"谁在传"和"这是谁的数据"彻底分开。传的一方是网关——一条连接、一个 clientId、一套 TLS;数据的一方是子设备——各自的物模型、各自的子表、各自的影子、各自的在线键。中间那层identity就是两者之间的翻译。它让一台网关可以体面地替三十台设备说话,也让平台在面对三十份数据时,不必知道它们是从哪条连接来的。---

2026-11-04 07:33:37 206

原创 SagooIoT 的数据接入层只有四张表,却能接住三种外部数据

四张元数据表,三个来源类型,两个合并策略,一个GET接口。从代码量上看,datahub在专业版里不算大,四千四百多行,比设备管理、告警、规则引擎都小。让"第三方数据"和"设备数据"在同一个模型里对话,而不需要为每个项目写一套一次性脚本。下次再有人问"你们平台能不能对接我们现有的 ERP 数据",答案不是"可以定制开发",而是"新建一个数据源,把字段拉一下,点发布"。

2026-11-03 07:35:03 157

原创 固件推下去了,SagooIoT 怎么确认设备真的装上了?

回头看,SagooIoT 的 OTA 做的事情可以概括成四句话。用模块、包、批次、明细四层把"发什么"和"发给谁"彻底拆开,包可复用、批次可停启、明细可逐台追。签名在服务端对落盘字节重算,不采信任何外部传入的值;url 与 ossurl 分开,签名和下载各走各的。下发有推、补、拉三条路:在线立刻推,离线等上线补,设备自己问就登记并给地址。三条路彼此不重复。状态由设备回执驱动,收口由平台自动完成。人只发起,剩下的交给 step 和那一次上线检查。

2026-11-02 07:37:11 220

原创 单机、哨兵、集群:SagooIoT 把三种 Redis 部署收进一个字段

回头看开头那三件事:换哨兵、换集群、换多地址,它们在这套代码里被收敛成「改mode和address两行」。支撑这个结论的不是 switch 本身,而是 switch 三段的参数完全对齐、地址统一按列表解析、对外只暴露这一层抽象。真正让部署形态可以随时切换的,是「连接的行为特征不随部署形态改变」这件事。另一半在连接管理上:两种用连接的路径各司其职,Pipeline 固定落一条连接,连接错误与业务错误分开处理,池子按操作类型分组并带上下限,健康检查每 30 秒把「够不够用、回没回来」写成一行日志。

2026-11-01 07:34:13 184

原创 跟着一条属性报文走一遍 SagooIoT 的接入链路

它进站时只是一段 96 字节的字节流,出站时已经变成了四种形态:时序库里的历史、缓存里的当前值、规则引擎的输入、业务系统的消息。从我被 Broker 收到,到我变成时序库里的一行、缓存里的一份影子、告警规则里的一个输入、业务系统收到的一条北向消息,中间隔着十几步。十二步里,只有第 6、7、8 三步是"必须当场算完"的,其余都可以异步、可以批、可以延后。状态更新只是"记一笔这设备刚说过话",和报文处理没有依赖关系,让它独立跑,业务侧就不会被它拖慢,它也不会因为业务侧排队而延迟。前面走的都是 MQTT。

2026-10-31 07:34:34 166

原创 SagooIoT 用一份物模型同时决定表结构与取值

物联网平台里最容易出问题的地方,往往不是协议对接,而是「同一个物理量在不同环节有不同解释」:设备说 235(0.1℃ 为单位),平台说 23.5℃,数据库存 23(INT),大屏显示 24。每一层都做了自己的四舍五入,最后一圈下来谁也对不上。SagooIoT 的处理方式是把解释权收归一处——物模型说它是 float、两位小数、量程 -40~85,那么解析、告警、影子、时序库、北向全按这个口径来。表结构是它算出来的,值是它裁剪过的,时间是它补齐的。一份配置,管住了从报文到曲线的整条路。---

2026-10-30 07:36:18 346

原创 把规则链存成文件之后,上线一条规则只需改一个字段

规则链是配置,配置就该是文件。因为配置是文件,所以一条链是一个 JSON,cp就是复制,git就是版本管理。因为配置是文件,所以状态只需要一个disabled布尔位——文件在不在是"有没有",disabled是"跑不跑",不需要第三第四个状态。因为配置是文件,所以加载失败可以直接把错误写回文件,让失败原因跟着规则走。因为配置是文件,所以热更新只需重新读文件、原地ReloadSelf,不用重启进程。而"看得见"这件事,是这套设计能落地的另一半。

2026-10-29 07:34:19 206

原创 SagooIoT 每秒刷新的大屏,靠一条不会结束的 HTTP 响应

SagooIoT 里已经有一套 WebSocket 了——设备接入隧道用一条,前端实时推送用另一条。既然有 WebSocket,为什么监控面板还要单独做一套 SSE?维度SSEWebSocket方向服务端 → 客户端单向双向协议普通 HTTP,文本独立握手,文本/二进制帧自动重连内置,带要自己写代理/网关与普通 HTTP 请求一致部分老代理会拦 Upgrade断线语义一次请求结束 = 该重连要维护连接状态机服务端实现一个 handler +Flusher。

2026-10-28 07:36:05 174

原创 影子不是缓存:SagooIoT 为什么要为每台设备维护两份状态

回到开头那张对不上的表。两份状态、四个元数据字段、一条只增不减的版本线、十个写协程和一个每分钟的检查器——pkg/shadow这一千四百多行其实只在做一件事:把"设备现在是什么"和"我们希望它是什么"这两个问题分开存、分开答,并且在两者之间留一条能查、能等、能超时的路。物联网系统里最难处理的状态,从来不是某一时刻的值,而是"值在变化中"的这段时间。设备离线、指令在途、固件重启、网络抖动,这些情况占掉了大部分运维精力。

2026-10-27 07:33:07 204

原创 SagooIoT 把协议解析和消息通知都放进了独立进程

回头看这九个二十多兆的文件,能让它们各就各位的其实就四件事:一是边界窄。跨进程只传DataReq和JsonRes,一个字节片进、一棵 JSON 树出,插件内部怎么实现,宿主不管。二是契约小。协议插件三个方法,通知插件两个方法,Info()自描述,EncodeDecode对称,Send一个参数。三是身份清楚。MagicCookie 对暗号,文件名定 ID,info.json描述元信息,表决定启不启用。四是生命周期有人管。懒启动省内存,人工启用可预热,五秒心跳防孤儿,并发 Kill 保退出干净。

2026-10-26 07:33:50 178

原创 SagooIoT 的观测入口只有一个,出口有三个

可观测性这件事,难点很少在"要不要做",而在"接在哪里"。接在每个进程的main里,十个进程就是十份重复代码;接在一个统一入口上,加进程只需要复制一段main。里一行InitTrace,配置里一个,日志靠 gf 的全局配置,剖面靠。三个开关、一个入口,剩下的都是适配器的事——把标准库的、slog的、Broker 的日志,统统导进同一份文件。代码量不大,一百多行、一百来行,但把"起不来时也能看见"、"退出前把队列刷干净"、"两种地址写法都能接"、"两个地方都能关日志"这些容易漏的边角都照顾到了。

2026-10-25 07:33:54 226

原创 设备报文怎么变,SagooIoT 只约定三个函数名

设备接入这件事,难的部分从来不是"支持多少种协议",而是"这一台和上一台差在哪"。差在字段名,就不该动代码;差在字节序,才该动插件。SagooIoT 用一个字段和三个函数名(parsesendreply),把前者从编译期挪到了运行期。它不是什么新概念,但确实把现场那句"这个要排期"变成了"这个我自己改一下"。

2026-10-24 07:33:32 138

原创 SagooIoT 的上下线事件全部来自 Broker 的 $SYS 主题

上线是SetExif err!= nil {g.Log().Debug(ctx, "更新设备交线状态失败", err)return为什么不是Del?因为平台里"设备离线"不止一个来源:MQTT 的断开事件、TCP 通道的心跳超时、数据上报里超过的静默。如果每个来源都自己去写离线态,就会有三份实现、三种边界、三个地方的隐患。把状态键的寿命改短。真正执行离线处理的是键过期事件。的init()于是无论离线是"Broker 说断了"、"心跳超时了"还是"很久没数据了",最后都走同一条内存路径。

2026-10-23 07:34:35 290

原创 SagooIoT 的缓存换后端只改一行配置,文件后端连 Redis 都不需要

把这套缓存拆完,会发现它的技术含量不在某个巧妙的算法上,而在几个"边界划得干净"的决定:配置是三选一,装配只有一处,业务侧只有一个入口;文件后端用 sha256 把任意键折成合法文件名,用绝对时间戳记到期,用读路径做惰性过期;键名统一带前缀,让"摘一条"成为默认操作而不是最后手段;常驻的配置类数据和带 TTL 的状态类数据分开对待,各用各的失效方式。这些东西单看每一条都很朴素。但物联网平台的缓存层最容易出的问题,恰恰不是性能不够,而是"不知道哪份数据是旧的"。

2026-10-22 07:35:14 350

原创 我们怎么把多种时序库接到同一套业务上

pkg/tsd是个挺可惜的包。它的骨架是对的:接口在tsd、数据结构在comm、实现在internal、工厂在最外层,依赖方向干净;tdengine那一套 SQL 拼装虽然朴素,但建超级表、建子表、加标签、加字段全都真做了,column()里物模型类型到 TDengine 类型的映射也是完整的一比一。问题出在"第二个实现"上。能空的空着,能恒真的恒真,能删的删数据。36 个方法里有 12 个到了这个状态,而接口上没有任何一处提示。这件事的教训不在"代码写得糙",而在抽象的顺序。

2026-10-21 11:08:37 229

原创 专业版守核心,企业版做增量:SagooIoT 的跨模块能力出口

SagooIoT采用专业版与企业版双module分层架构,通过Go的internal机制隔离核心实现,以pkg/proxy为唯一跨模块调用出口,确保专业版独立演进、企业版灵活增量。该设计实现核心能力纯净、业务复用统一、交付组合灵活,避免代码污染与耦合,提升可维护性与扩展性,是物联网平台分层演进的工程化实践。

2026-10-20 07:34:21 199

原创 SagooIoT 设备日志攒批进 Redis,卡在一把锁和一个提前返回上

一个批处理器的正确性,很少取决于它"攒了多少条",而取决于它在三种异常下的行为:Redis 慢了、写失败了、进程要关了。SagooIoT 这一层在前两种上还算有交代(超时、失败保留重试),在第三种上则是空的——注释承诺了刷盘,代码在刷盘前就把自己关掉了。更值得注意的是一种模式:这套代码里几乎所有问题都不是"写错了",而是"写对了但没接上"。构造函数默认 20、配置默认 50、yaml 里写着 20,三个数字各自成立,凑在一起就是没人说得清实际值;Stop和FlushAll。

2026-10-19 07:33:42 165

原创 接了 8 种工业协议我才明白,「支持多少种协议」是个伪指标

某20年老厂改造中,面对9类设备、8种工业协议,甲方要求不换设备、不停产、3个月上线。作者仅用11天完成接入,核心在于突破“协议支持数量”伪指标,聚焦语义层非标问题:如DL/T645密码为BCD编码、CJ/T188字节序矛盾、S7读写Length语义不同等。通过抓包验证、逐点通读、差分计量、时间同步等实战方法,实现高效对接。关键启示:手册不可靠,真实报文才是标准;统一出口与隔离故障,比协议数量更重要。

2026-10-18 10:36:16 324

原创 SagooIoT 的 MQTT 客户端把订阅记在一张表里,但有人绕过了那张表

MQTT 的订阅是一份服务端状态,而让它变成了一份易失状态。任何在客户端缓存这份状态的封装,本质上都在做一件危险的事:替服务端记账。要记对,前提是所有写入都必须经过同一个账本。SagooIoT 这张表记对了核心侧,漏掉了规则引擎侧。漏掉的原因不是疏忽,而是封装只提供了「更好走的路」,没有堵住「另一条路」。这种设计在功能验证阶段毫无问题——订阅确实成功了,数据确实在流;只有在断线重连这个低频路径上,两条路的差异才会显现成一次没有日志的数据中断。绕过它会不会立刻出问题。

2026-10-18 07:33:39 232

原创 MQTT 不回话,SagooIoT 给下行指令补了一个应答信箱

用 Redis 的两个命令,给不开 request/response 的 MQTT 装了一层 request/response。是登记,TTL 和超时对齐,过期即作废;是交付,配对成功才发;是等待,一次只认第一条;两个池(channel 池、协程池)负责把等待的成本压住。发指令,sagoo-core收设备回话。这个前提一旦成立,那么"信封放哪、回执发哪、超时谁管"这三个问题就没有太多别的答案了。只做一次配对,不重试、不持久化、不追溯。回执超时就是失败,前端重试由用户决定。

2026-10-17 07:33:52 197

原创 SagooIoT 的定时任务躺在 Redis 里,靠一把 15 秒的锁推进

pkg/worker队列用现成的,调度自己写。asynq 负责一次性任务的延迟、重试、归档和批量聚合;周期任务被压进一个 Redis hash,由每 3 秒一次的扫描推着走,实例之间用一把 15 秒的锁排他,抢不到锁的实例会自己把扫描间隔从 3 秒慢慢退到 10 秒。白名单 +分隔的参数 +CallMethod反射,把「写一个方法」变成了「在后台配一条记录」。代价是这层胶水没有编译期保护,错误只会在运行期以 Debug 日志的形式出现。

2026-10-16 07:34:45 189

原创 连上来的是设备还是浏览器?SagooIoT 两条 WebSocket 通道的分工

它没有追求「一套 WebSocket 框架打天下」,而是按对接方的性质分别实现。设备侧面对的是「连接数可控、报文是字节流、必须记住隧道状态」,所以走独立端口、URL 定身份、二进制帧、隧道入库、上线/下线有明确动作。前端侧面对的是「连接数多、消息是文本、可以不关心连接状态」,所以走主服务、纳秒 ID、文本帧、无缓冲队列、心跳靠 TCP。两种做法都不复杂,难的是别把它们搅在一起——这正是我在读这套代码时觉得最值得记下的一点。

2026-10-15 07:34:07 263

原创 令牌有效,会话已死:SagooIoT 双层令牌的时间窗、续期与吊销

回到开头那张截图。那个exp还有两天的 JWT,确实还有效——只是它已经不在缓存里了。可能用户点了退出,可能管理员把账号禁用了,也可能只是那把EncryptKey换了。无论哪种,平台给出的答案都一样:会话不存在,令牌就是废纸。识别交给 AES 外壳,信息交给 JWT,存在性交给一条带 TTL 的缓存记录。三者各管一段,于是吊销变简单了(删 key),续期变无感了(进窗口重签),claims 也不用下发了(JWT 留在服务端)。代价也很清楚:它不再是"无状态"的。每请求一次要查一次缓存。

2026-10-14 07:34:34 110

原创 线拔了,状态还亮着:SagooIoT 设备在线判定的过期键、两级缓存与上下线链路

回到开头那台被拔了网线的网关。它之所以还亮着,是因为平台对它的最后一次确认发生在 120 秒之前,而这段时间里没有任何信号告诉平台"它走了"。这不是疏忽,是这套机制的显式代价:用"等 TTL 自己到期"换来的是 O(1) 的写入、O(1) 的判定,以及在几万台设备规模下都不需要聚合查询的状态列表。一条带 TTL 的键,把"最后活跃时间"压缩成"是否还在";一个 10 秒的本地副本,把最热的读挡在进程内;一次expired订阅,把被动轮询变成主动通知;三套订阅自检,让这条链路能活过一夜;

2026-10-13 07:33:57 226

原创 一套能真正交付的物联网开源平台 — SagooIoT

SagooIoT 是一个面向交付的开源物联网平台,解决设备接入后“规则、组态、大屏”难整合的痛点。基于 Go + Vue 3 构建,集成物模型管理、可视化规则引擎、组态工具、视频监控、数据大屏等六大核心组件,支持工业协议(Modbus、OPC UA、IEC 104 等)与边缘离线运行,具备告警治理、场景联动、远程升级等运维能力。提供免费试用与透明授权,5 分钟即可部署,适合工业、园区、系统集成等需完整交付的项目,真正实现“接得进、跑得动、交得出”。

2026-10-13 06:25:56 159

原创 一条消息一个 go,程序先把自己拖垮:SagooIoT 协程池 gpool 的并发闸门、排队与扩缩容

回到最开始那行。它最大的问题不是慢,而是没有边界。设备规模一上来,程序不会温和地变慢,它会先在某一次流量尖峰里崩掉——而且往往不是在收报文的地方崩,是在内存里崩。gpoolsem决定同时多少人干活,taskQueue决定等多久,决定涨到哪,10 秒超时决定一个人最多占位多久。它不追求炫技,用的都是channelsync.Poolatomic这些最朴素的零件,但每一处取舍都指向同一个目标——让并发有上界,让任务不丢。如果你也在写"一收数据就go我的闸门开多大,队列留多长,超时给几秒。

2026-10-12 07:33:49 63

原创 读数是 1008,用电量是 8:SagooIoT 计算服务的增量口径与七种计算策略

回到最开始那块电表。它到今天还是只会报一个绝对读数,不回答"今天用了多少"。中间的差值,得由平台替它算——而且得算得可复现、可解释、能被翻出来对账。SagooIoT 计算服务做的事,就是把这类"算"收进一个统一的入口:七种策略,一个Compute接口,参数不合适就挡在Validate,跑太久就收敛成ErrTimeout。它不追求大而全,而是把"读数→增量→累计"这条最常走的路走得干净,把窗口、聚合、触发拆成正交的参数,让一条业务规则能靠组合拼出来,而不是靠新加一个策略。

2026-10-11 07:35:54 314

原创 同一个值,四个名字,四套口径:SagooIoT 属性上报链路的 Canonical 收敛

给属性上报链路做基线是一件很枯燥的事:固定 10k 设备在线、10k msg/s、每条报文 500 字节上下、平均一条报文带 5 个属性,然后让 benchmark 跑三轮。跑完拿到的第一个数字有点刺眼——一次属性上报,在热路径上要做。67 次里面真正属于业务的没几次。剩下的大部分花在同一个值被反复改名、反复转换上:进来时叫报文字节,解完叫 params,归一后叫 ReportPropertyData,发给下游时又要变成各自投影过的形状。

2026-10-10 16:51:42 212

原创 告警响了一整夜,通知只发出去三条:SagooIoT 告警治理的合并窗口、抑制频率与级别升降

告警治理的难点不在算法,在取舍,而且取舍的结果往往体现在几个不起眼的地方:一条正式告警的键只有来源和类型,所以"什么算同一件事"这件事,其实是由生产方填标签时决定的;合并取最严重的一条、描述只留 5 条,所以Count比更接近真相;升级看CreatedAt、降级看UpdatedAt,两个时间基准不一样,级别会自己往上浮;而频率阈值和通知间隔这两个配置项,因为读写两侧的键名没对齐,目前在默认实现下是空转的。平台做的事,是把这一堆取舍收进一个后台模块里:对外只有一个,进去是原始告警,出来是"该不该惊动人"

2026-10-10 07:47:09 316

原创 标签找得到,值接不上:SagooIoT 接入 EtherNet/IP 的会话、路径与类型

EtherNet/IP 接入的难点不在协议本身,而在四个"看不见"的地方:标签名要变成 EPath 才发得出去;"TCP 通了"之后还有注册会话与开连接两次交互;值的类型是控制器说了算、平台只能接住或接不住;而失败又常常被逐点采集的容错策略吃掉一半。平台做的事,是把这些差异收进一个插件进程里,让上面看到的还是同一套东西——一个点位、一个属性、一条采集周期。标签路径、CIP 路径、类型映射这些协议自己的语言,止步在插件边界。主仓库:https://github.com/sagoo-cloud。

2026-10-09 11:39:07 166

原创 KNX 现场没有寄存器表:SagooIoT 楼宇驱动插件的组地址、DPT 与隧道

在 Modbus、Siemens S7、HART-IP 这些协议里,"读一个值"有明确的因果:平台发一个请求,设备回一个响应,一问一答,谁问、谁答、答的是哪一条,全都是确定的。KNX 不是这样。它的总线是事件型的——温度传感器自己决定什么时候广播一次测量值,开关面板自己决定什么时候广播一次按下动作,没有谁在等谁。平台想拿一个当前值,能做的只是"问一声",然后等总线上有没有人愿意接这句话。有的点会接,有的点永远不接:它只在自己状态变化的时候广播一次,从来不理别人的询问。

2026-10-08 09:15:55 248

原创 4-20 mA 走上网线之后:SagooIoT 接入 HART-IP 的会话、命令与字段

在 SagooIoT 里换一个采集协议,最先要改的往往不是代码,是"点位"这个词的含义。Modbus 的点位是一个寄存器地址,EtherNet/IP 的点位是一个标签名,而 HART-IP 的点位是一对(命令号,响应字段)。这个差别不是命名习惯,它来自协议本身的出身:HART 是长在 4-20 mA 模拟回路上的一套数字协议,一条回路上本来只有一个"当前值",没有地址空间可以编,读什么值靠的是"发哪条命令"。

2026-10-07 09:08:54 209

原创 先应答,再入库:SagooIoT 接入 GB/T 32960 的四层宿主改造

这次改造真正有意思的地方,不是协议本身——GB/T 32960 的编解码在国标文档里写得足够清楚,一个熟练的 Go 工程师照着抄一遍大概两三天。有意思的是平台为了承接它必须改什么。"只写一个协议插件就够了"这个假设,在遇到第一个会话型二进制协议时就破了。帧从哪切、连接属于谁、回应写到哪。这三件事必须由宿主提供,插件才有条件把自己的协议逻辑写好。反过来说,宿主提供的这三样能力必须是可选的、默认关闭的。

2026-10-06 09:16:05 289

原创 同一个寄存器,四种读法:SagooIoT Modbus 驱动的字节序、宽度与功能码

把 1.5 这个数写进两个连续的保持寄存器,再读回来,你可能拿到 1.5,也可能拿到 1078984704;把 25.6 写进一个输入寄存器再读回来,可能还是 25.6,也可能变成 2560。这不是设备坏了,是同一个寄存器在不同的配置下有四种读法。Modbus 从 1979 年活到今天,靠的是极简——一张功能码表、四块存储区、一个大端字节序。而恰恰是这份极简,把「读几个」「按什么顺序拼」「拼出来怎么解释」这三件事全推给了上位机。现场九成的「采到的数不对」,最后都落在本文要讲的这几处。

2026-10-05 09:08:52 276

原创 一个点位,十八种说法:SagooIoT 工业协议驱动插件的共同骨架

驱动插件是主动去问设备的。同一台 PLC 上挂十几个属性、轮询周期又短的时候,平台必须保证同一时刻只有一个请求在飞——Modbus TCP 的一个连接上并发发两条读命令,响应会串在一起。平台的解法是按"连接"加锁。// DriverCapabilities 驱动运行时能力声明。// WriteMode 属性写入模式:smart_key(默认,仅接受 {key,value})// CollectionMode 采集模式:poll / push / subscribe。

2026-10-04 09:12:48 195

原创 插件是个独立进程,不是一份配置:SagooIoT 协议插件开发实操

把一种私有协议接进 SagooIoT,最后交出去的是两样东西:一个编译好的可执行文件,和一个几十行的info.json。压成 zip,从后台上传,插件列表里点一下启用,这条路就通了。平台不用重启,也不用改一行平台自身的代码。代价是得先接受一个设定:你的解析代码不会跑在平台进程里,它会跑在另一个进程里。这个设定决定了后面几乎所有细节——接口签名为什么长这样、传参为什么是[]byte、日志为什么会出现在平台的日志里、插件崩了平台为什么还活着。

2026-10-03 09:06:38 245

原创 权限改了,接口立刻生效,菜单要等重新登录:SagooIoT 权限体系的四道闸门

给一个角色勾完权限,点保存,接口返回 200。让那个用户刷新页面——菜单还是旧的。这不是 bug。在 SagooIoT 的权限体系里,"这个接口你能不能调"和"这个菜单按钮显不显示"走的是两条路:一条每次请求都去数据库问一遍,另一条的结果被缓存到用户下次登录为止。两边的生效时间自然对不上。要把这件事讲透,得先认全它背后的六张表,再跟着一次请求把四道闸门走一遍。

2026-10-02 09:17:02 128

原创 换票的事,平台替你做了几次:SagooIoT HTTP API 数据源的鉴权与 Token 缓存

面向的是"响应不是标准格式"的登录/换票接口,比如 token 藏在或里。字段默认必填说明鉴权请求方法POST否GET / POST鉴权请求地址是登录或换票 URLToken 字段路径建议gjson 点路径,如data.token有效秒数建议响应无expires_in时的兜底(界面常填 7200)注入参数名否写入业务请求的参数名注入模板否用{{token}}占位注入位置header否headerquery鉴权请求 Body{}视接口JSON 对象,

2026-10-01 09:12:43 161

原创 消息是怎么在链子上消失的:SagooIoT 规则引擎执行侧的路由、脚本与副作用

规则引擎的难点从来不在画图上。这条消息现在在哪,下一步为什么没动。而要回答这个问题,就得知道每根线的语义、每个脚本拿到的是什么类型、每个默认值意味着什么。上面十一节里的每一条,都是这个问题的一个侧面。开源组织:https://github.com/sagoo-cloud在线文档:https://iotdoc.sagoo.cn规则引擎的节点文档在文档站的「IoT 平台 → 规则引擎」下,共 45 份,本文只覆盖了执行侧那 32 份里被问得最多的部分。

2026-09-30 09:21:03 58

基于P2P方式的即时通讯源码

程序说明: 1.程序采用网上介绍的方法实现最基本的P2P方式通讯.模拟实现即时消息互发. 2.P2P通讯说明: 1).网关类型是在理想状态下.即非对称型NAT. 2).同在一个内网的两个CLIENT端通讯时,如果网关NAT不支持环回,将会失败. 文件目录说明: tQServer:程序服务端,请将其放在公网上运行. tQClient:程序客户端,可以在不同的内网中运行登录连接到服务端. Common:公共协议文件夹 本程序只是实现简单的P2P互发消息.完成的比较粗糙,更多功能欢迎朋友们更新完善..

2005-12-23

Delphi最新三层源码 1.0

//数据连接类  IConnDB in 'DBConnection\IConnDB.pas',   ConnDB in 'DBConnection\ConnDB.pas',   ConnDB_ACCESSServer         in 'DBConnection\ConnDB_ACCESSServer.pas',  ConnDB_SQLServer         in 'DBConnection\ConnDB_SQLServer.pas',  ConnDB_ORACLEServer         in 'DBConnection\ConnDB_ORACLEServer.pas',  ConnDBFactory in 'DBConnection\ConnDBFactory.pas',  ConnDBFactory_ACCESSServer       in 'DBConnection\ConnDBFactory_ACCESSServer.pas',  ConnDBFactory_SQLServer       in 'DBConnection\ConnDBFactory_SQLServer.pas',  ConnDBFactory_Oralce      in 'DBConnection\ConnDBFactory_Oralce.pas',  ConnDBConfig in 'DBConnection\ConnDBConfig.pas',  //VO及VOLIST类  valueObjectUnit in 'DAOObject\valueObjectUnit.pas',  valueObjectListUnit in 'DAOObject\valueObjectListUnit.pas',  IvalueObjectListUnit          in 'DAOObject\IvalueObjectListUnit.pas',  DynamicDataSetUnit          in 'DAOObject\DynamicDataSetUnit.pas',  valueObjectDBListUnit          in 'DAOObject\valueObjectDBListUnit.pas',  VOPrototypeManagerUnit in 'DAOObject\VOPrototypeManagerUnit.pas',  //DAO类设计  IDAOvalueObjectUnit in 'DAOObject\IDAOvalueObjectUnit.pas',  DAOvalueObjectUnit in 'DAOObject\DAOvalueObjectUnit.pas',    //服务类设计  ServiceObjectUnit in 'Service\ServiceObjectUnit.pas',  SQLAnalyzeServiceUnit in 'Service\SQLAnalyzeServiceUnit.pas',    //业务对象类设计  BOPrototypeManagerUnit in 'BusinessObj\BOPrototypeManagerUnit.pas',  BOServiceUnit in 'Service\BOServiceUnit.pas',  IBaseBOUnit in 'BusinessObj\IBaseBOUnit.pas',  BaseBOUnit in 'BusinessObj\BaseBOUnit.pas',

2005-12-23

java实用工具包(新手型)

针对2维表数据的分页。不针对各种不同数据库为了提高效力而使用的分页读取。 对各种有可能转化成2维表数据的数据先通过自定义的转化器转化成ArrayList(HashMap)或 ArrayList(javabean) 如果类型为ArrayList不需要转化,已经写了2个,分别为ResultSet和Vector,其它特殊类型的转化自己实现SourceConv接口,并在SourceConvFactory中注册(注册没有 写在配置文件,自己按需要去完善 :) ) 对第2维的格式化(即列数据),通过实现PageCol接口,已经有javabean和hashmap两种的格式化 import com.miphone.newcard.source.*; import java.util.*; 1.ArrayList source=.......; //不需要转化 2.ResultSet source=.......; //需要在后面添加 tool.setSourceType("ResultSet");已经有一个SourceConv的子类处理 //ResultSet的格式化 3.Vector source=........; //需要在后面添加 tool.setSourceType("Vector");已经有一个SourceConv的子类处理 //Vector的格式化 4.OtherObj source=......; //自己实现SourceConv接口,并在SourceConvFactory中注册,需要在后面添加 tool.setSourceType("名字","class路径及名称"); 5 tool.setSourceColType("列数据类型名");//默认为HashMap,已经有HashMap和javabean的实现,javabean需要 tool.setClassName("javabean类名"); 6 tool.setSourceColType("列数据类型名","类名");//自定义的列数据格式 PageTool tool=new PageTool(); tool.setSource(source); Vector cols=new Vector(); cols.addElement("id"); cols.addElement("name"); cols.addElement("value"); cols.addElement("type"); cols.addElement("note"); tool.setColNams(cols);//设定读取字段 tool.setPageSize(10);//设定pagesize String[] infos = {"<img src='1' >", "<img src='1' >", "<img src='1' >", "<img src='1' >", "<img src='1' >"}; tool.setPageInfo(infos);//设定分页的显示,默认为{"页次", "首页", "上一页", "下一页", "尾页"}; tool.setHrefName("search.jsp"+args);//分页显示的指向超链接。如 search.jsp?id=1 String thispage=request.getParameter("page"); tool.makeCurrentPage(thispage);//设定当前页,thispage的判断由PageTool自己控制。 tool.Create();//生成分页 //读取 while(tool.next()){ String id=rs.getString("id"); String id2=rs.getString(1);//下标从1开始 String name=rs.getString("name"); String name2=rs.getString(2); } rs.free();//不是必须得,在重复利用时需要用来清空已经有数据的对象。 /* 分页显示方法 */ tool.getFirstPage(); tool.getForwardPage(); tool.getNextPage(); tool.getLastPage(); tool.getTotalInfo(); tool.getRecordCount(); tool.getPageSize();

2005-12-15

Netbit Browser嵌入式浏览器(论文+源码)

全文公62页,写的很专业,包括论文全文、论文答辩PPT讲稿、源代码。 摘 要 本文主要论述了嵌入式浏览器开发所涉及到的技术,对HTML词法分析、浏览器JavaScript支持、linux和gtk编程等做了详细的分析和介绍,并对Netbit浏览器的开发进行了介绍,分析了主要的模块的功能和组成,并给出了主要算法。 还对典型的嵌入式浏览器进行了分析,包括Gzilla,Mozilla,Thunder和zen,总结了浏览器设计的技术要点和开发策略。 另外,在论文开头,介绍了目前嵌入式浏览器产品的发展现状,嵌入式浏览器的组成和各部份功能说明。 HTML词法分析是着重讨论的技术问题,给出了详尽的数据结构,程序流程。 Netbit浏览器的开发,是本论文的重点,分模块进行了分析,提出了需要改进的地方,并给出了改进措施。 关键词:嵌入式浏览器,HTML词法分析,Javascript,linux,gtk ABSTRACT This paper is focused on the technology of embedded browser.Html scanner, JavaScript support for browser, linux and gtk programming are deeply discussed.and introduce the development of Netbit browser, analyse the main module of Netbit, the algorithm is presented. what’s more, other typical embedded browsers are analysed, include Gzilla,Mozilla,Thunder and zen,and summarize the important technology and the policy of browser development In addition,at the head of the paper,introduce the present status of embedded browser product,the general form of embedded browser and description of the main parts. HTML scanner is an important technological problem, the data structure and the flow of the program are presented. The development of Netbit Browser is mainly discussed,and analysed by module,give the opinion to improve it. KEY WORDS: embedded browser,HTML token,Javascript,linux,gtk 目 录 引言………………………………………………………………5 第一章 嵌入式浏览器设计概述 ………………………… 6 1.1目前嵌入式浏览器产品的发展现状 ……………………… 6 1.2嵌入式浏览器的组成和各部份功能说明 ………………… 8 1.3开发难度分析 ……………………………………………… 9 1.4开发的前期策划 …………………………………………… 10 第二章 HTML词法分析器的设计及其应用 …………… 12 2.1 Bit Token的组成及其功能 ………………………………12 2.2 数据结构 ……………………………………………………12 2.3 算法 …………………………………………………………13 2.4词法分析结果示意……………………………………………15 2.5 HTML词法分析的应用 ………………………………………15 第三章 浏览器JavaScript支持的实现 …………………18 3.1基本的JavaScript 开发环境 ………………………………18 3.2 JavaScript Engine …………………………………………18 3.3 JavaScript与浏览器接合 ………………………………… 19 3.4 浏览器消息响应 …………………………………………… 21 第四章 Linux程序开发技术及 GTK图形程序开发…… 23 4.1 Linux下的程序开发环境 …………

2005-12-28

Bea WorkShop Studio (NitroX M7) 系列注册机

拷贝这个注册机到下面目录运行: ....\plugins\com.m7.nitrox_3.0.0 这个注册机能破解NitroX 所有的IDE。 另外,用这个注册时你不需要断开网络。 只支持JDK1.5. 只要把注册表的HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft下的关于1.4的jre和jvm的路径信息改为1.5的jdk的即可。 如果只能用workshop for struts, 不能用HIBERNATE 和JSF 你只要注册成WorkShop Studio, 所有的功能都能用了。 你不用重新安装,只要把....\plugins\com.m7.nitrox_3.0.0 下面的 ins.properties 文件中 prodid 改成 prodid =0005, 重新注册就可以了。

2005-12-15

一个基于Struts+Hibernate+MsSql2000的实例

一个简单的用户登录验证,主要是用了Struts+Hibernate框架,工具Eclipse+Myeclipse!

2005-12-15

java实用工具包(大众型)--XML处理

让xml处理无门槛,你会爱上使用xml文件。 该包主要工作是封装,把操作简单明了化,可以让那些对document的东东望而生畏的人不用去"头痛",使用xml处理很简单明了。上面的3个例子只有取属性,其实还有advanceGetNode("path/map[0]")来直接获取节点,然后就可以针对节点addElement

2005-12-15

飞鸽传书Ver2.06源码

-------------------------------------------------------------------------------- 飞鸽传书 (IP Messenger) Ver2.06 Copyright (C) 1996-2004 SHIROUZU Hiroaki All Rights Reserved. -------------------------------------------------------------------------------- 目录: 1. 软件简介 2. 许可协议 3. 系统要求 4. 使用说明 5. 相关信息 6. 广域网设置(广播设置) 7. 补充 8. 支持 9. 更新历史 10. 感谢 ================================================================================ 重要说明: comctl32.dll(公共控件) 要求 4.71 或以上版本 更多信息请参见 "系统要求" ================================================================================ -------------------------------------------------------------------------------- 1. 软件简介 - IPMsg 是一款局域网内即时通信软件, 基于 TCP/IP(UDP). 可运行于多种操作平台(Win/Mac/UNIX/Java), 并实现跨平台信息交流. - 不需要服务器支持. - 支持文件/文件夹的传送 (2.00版以上) - 通讯数据采用 RSA/Blofish 加密 (2.00版以上) - 十分小巧, 简单易用, 而且你可以完全免费使用它 - 目前已有的版本包括: Win32, Win16, MacOS, MacOSX, X11, GTK, GNOME, Java 等, 并且公开源代码. 请查看以下地址以获得相关信息: http://www.ipmsg.org/ -------------------------------------------------------------------------------- 2. 许可协议 (BSD License) Copyright (c) 1996-2004 SHIROUZU Hiroaki All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the SHIROUZU Hiroaki nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRI

2005-12-14

软件成熟度模型CMM入门(PDF格式)

很多时候,人们提到CMM,其实指的是SW-CMM,即软件CMM。除了SW-CMM以外,还有P-CMM,SE-CMM,SA-CMM和CMMI等,这些CMM都是美国Carnegie Mellon大学软件工程研究所(SEI)的产品。每个CMM都是独立的产品,有各自不同的用途,但这些CMM之间也有一定的渊源关系。即使同一个CMM也有版本之分,例如SW-CMM,有1.0版本,也有1.1版本。当然,其他机构或者公司也可能有“某某CMM”的东西。因此,我们通常所说的CMM,确切的完整的说法是SEI SW-CMM v1.1。在以后的文字中,如果不加说明,CMM即指SEI SW-CMM v1.1。 CMM是Capability Maturity Model 的首字母缩写,翻译成中文:能力成熟度模型。顾名思义,它是一个“模型”。既然是模型,那一定有对应的实体,CMM对应的实体就是软件组织。软件组织的规模可大可小,可以是一个软件公司,也可以是一个部门,但它们存在的目的是相同的,都是为了生产软件。 概括而言,CMM是一个用来描述,或者说,表示软件组织的模型。

2005-12-23

JPEG图象解码程序

JPEG解码源码,Delphi源码。其实,JPEG解码可以用用Intel提供的ijl15.dll库,还是不错的。

2005-12-31

图像融合算法演示源码

点击打开文件的两个按钮,打开上下文件然后在图片上用鼠标左键点击选择一个闭合的区域,当两个图片区域选定后,点击生成比对图片按钮,将会生成融合的比对图片,您可以调整比对图片的相对位置和图片透明度。

2005-12-31

扫雷(MVC架构)

把JAR包解压后有所有源码! 同样基于MVC,并力求在源码中合理使用设计模式

2005-12-15

点对点传输控件P2PSock 源码

点对点传输控件P2PSock For D6

2005-12-23

MyEclipse4.1.0破解文件

用winrar打开\MyEclipse\eclipse\plugins\com.genuitec.eclipse.core_4.0.3\core.jar文件,找到C.class所在的目录。 2、下载附件。如果附件下载不了试试看,这个网址:http://www.bloghome.cn/download.php?ownerId=7&resource=myeclipse_enterprise_4.0_Crack.rar&pid=39558 3、用winrar打开刚下载的文件,找到C.class文件,然后用鼠标将C.class拖到第1步打开的目录。 4、启动myeclips,新建一个myeclips工程。myeclips会弹出一个对话框,提示你30天试用。 5、注册Subscriber: Subscriber: Hello Subscription Code:UAR7ZL-955-56-54674676067481865 恭喜你,你已经完全拥有myeclips了!!

2005-12-30

计算机软件需求说明编制指南(DOC格式)

本指南为软件需求实践提供了一个规范化的方法。本指南不提倡把软件需求说明(Software Requirements Specifications,以下简称SRS)划分成等级,避免把它定义成更小的需求子集。 本指南适用对象: 软件客户(Customers),以便精确地描述他们想获得什么样的产品。 软件开发者(Suppliers),以便准确地理解客户需要什么样的产品。 对于任一要实现下列目标的单位和(或)个人:

2005-12-23

飞鸽传书Ver2.06

目录: 1. 软件简介 2. 许可协议 3. 系统要求 4. 使用说明 5. 相关信息 6. 广域网设置(广播设置) 7. 补充 8. 支持 9. 更新历史 10. 感谢 ================================================================================ 重要说明: comctl32.dll(公共控件) 要求 4.71 或以上版本 更多信息请参见 "系统要求" ================================================================================ -------------------------------------------------------------------------------- 1. 软件简介 - IPMsg 是一款局域网内即时通信软件, 基于 TCP/IP(UDP). 可运行于多种操作平台(Win/Mac/UNIX/Java), 并实现跨平台信息交流. - 不需要服务器支持. - 支持文件/文件夹的传送 (2.00版以上) - 通讯数据采用 RSA/Blofish 加密 (2.00版以上) - 十分小巧, 简单易用, 而且你可以完全免费使用它 - 目前已有的版本包括: Win32, Win16, MacOS, MacOSX, X11, GTK, GNOME, Java 等, 并且公开源代码. 3. 系统要求 Microsoft Windows 95/98/Me/NT4.0/2000/XP/2003 95/98/NT4.0 ... 要求 comctl32.dll(公共控件) 的版本为 5.x 或更高. (如果你安装的 IE 是 5.x 或更高版本, 那么就不必担心这个问题了) 注意: Windows 3.1(和 NT3.5x), 请使用 IP Messenger for Win16. -------------------------------------------------------------------------------- 4. 使用说明 < 安装/卸载 > 执行 setup.exe 你可以将 IPMsg 安装到指定目录, 或者重新注册到启动组. 如果需要删除 IPMsg, 请先从控制面板中卸载, 再手动删除 IPMsg 目录. < 系统托盘区图标 > 左键双击图标, 即可打开发送消息窗口. 右键点击图标, 可进入 [服务设置], [离开] 等. < 发送消息窗口 > - 发送消息时, 若勾选了 [封装], 则接收者要先打开信封才能看到消息, 如果你还勾选了 [上锁], 则接收者在打开信封时还需要输入密码. (密码是由接收者自己在 [服务设置] 中设置的) - 若要发送文件/文件夹, 可直接将文件/文件夹拖入发送消息窗口 或在发送消息窗口上点击右键, 再选择发送文件或发送文件夹 - 传送文件/文件夹时, 当接收者还没有保存(下载)文件/文件夹时, 若发送者关闭或重启了 IPMsg, 则附带的文件信息将被清除, 接收者将不能继续接收(下载)到此文件. - 用户列表前缀符号说明 ":" 表示用户处于离开模式. "|" 表示用户使用的不是 2.0 以上版本的 IPMsg, 将不支持文件/文件夹的传送, 并且不支持通信数据加密. "|"(短线) 表示只支持文件/文件夹的传送. - 拖动列表表头标题项可改变其顺序, 并可点击右键选择"保存列表顺序" - 在消息输入窗口中, 可使用 Ctrl+Tab 输入制表符 Tab. - 在发送消息窗口上点击右键, 可以进入设置显示优先级, 选择工作组, 搜索用户(Ctrl+F), 传送文件, 传送文件夹, 保存列表顺序, 字体设置, 窗口大小设置, 固定窗口位置, 列表显示设置. - 在用户名上点击右键, 可设置其显示优先级 优先级按由小到大的顺序排序 - 通过设置显示优先级, 可将经常联系的用户至于列表顶端, 或者隐藏不需要联系的用户 < 接收消息窗口 > - 在接收消息窗口上点击右键, 可以进入字体设置, 窗口大小设置, 固定窗口位置. - 接收消息窗口标题栏中的 "+" 或 "-" 表示通信数据使用了加密算法 "+" 表示 RSA/1024 位, blowfish/128 位加密 "-" 表示 RSA/512 位, RC2/40 位加密 - 如果你收到的消息附带了文件, 将会显示出附件按钮. 点击按钮即可保存文件. < 其他 > - 如果需要(通过路由器)连接到广域网, 则需要设置广播地址. 详见广域网设置(广播设置) - 其它功能都很容易理解, 你试一试就明白了 -------------------------------------------------------------------------------- 5. 相关信息 - 所有的设置信息都保存在注册表的以下位置: \\HKEY_CURRENT_USER\Software\HSTools\ 用户密码以不可逆加密方式存储. ******************************************************************* * 如果你忘记了密码, 可以在注册表中将此键值删除 * * \\HKEY_CURRENT_USER\Software\HSTools\IPMsgEng\PasswordStr * ******************************************************************* - 本软件使用的默认端口为 2425 若仅使用 UDP 协议的端口, 将不能传送文件/文件夹 (如果安装了防火墙, 则必须打开相应的 TCP 和 UDP 端口) - 本软件为自由软件, 你可以随意传播, 但源码使用请参见许可协议. - 只有在启动或退出程序, 使用离开模式, 刷新在线用户时 IPMsg 才会进行消息广播. - 本软件由 Microsoft Visual C++ 6.0 编译 -------------------------------------------------------------------------------- 6. 广域网设置(广播设置) - 主机号全部为 1 的 IP 地址, 即广播地址 例如, 连接到一个 C 类子网(即 24 位网络号, 8 位主机号), IP 地址为 aaa.bbb.ccc.ddd, 其广播地址即为: aaa.bbb.ccc.255 若对方处于另一个私有子网中, 广播可能无效. - 更多问题, 请参阅相关资料或咨询你的网络管理员. - 若两台主机的连接经过了多个路由器, 请直接指定对方IP地址 - 拨号上网用户请勾选 [拨号连接] 当刷新在线用户列表时, 列表不会被清空 -------------------------------------------------------------------------------- 7. 补充 - 启动飞鸽传书前, 你可以指定其运行时使用的端口, 且可以使用不同的端口打开多个窗口. 用法如下: ipmsg.exe 2426 (你可在快捷方式上设置) 但是你只能与同时也使用该端口的用户通信. - 所以你尽可选用你喜欢的端口运行本软件. 介于 10000 至 60000 可能更安全些. 你也可以咨询你的网络管理员. - 如果有多个网卡(IP), 你可以将飞鸽传书与指定的网卡(IP)进行绑定. 命令格式如下(你可以在快捷方式上设置): ipmsg.exe [端口] /NIC IP地址 例如: C:\>ipmsg.exe /NIC 192.168.10.100 - 支持命令方式发送消息 命令格式如下: ipmsg.exe [端口] /MSG [/LOG][/SEAL] <主机名或IP地址> <消息> 例如: C:\>ipmsg.exe /MSG /SEAL localhost Hello. - 操作技巧. 1. 隐藏/显示 窗口 Ctrl + D 2. 按住 Ctrl 键再点 [刷新] 可保持现有用户, 搜索新上线的用户 3. 打开发送/接收消息窗口 Ctrl + Alt + S / R (需要进行详细设置) 4. 打开搜索窗口 Ctrl + F 5. 接收到多个文件, 保存时可勾选 [全部] -------------------------------------------------------------------------------- 8. 支持 - IPMsg 的技术讨论区是开放的. 如果你想订阅相关邮件, 请联系 ipmsg-subscribe@ring.gr.jp - 欢迎报告 bug, 以及提出建议 - 如果你有任何疑问, 请 E-mail 联系. shirouzu@h.email.ne.jp 中文版可联系阿志: hiwyz@163.net - 发送错误报告, 请勿必记录以下信息: 软件版本, 操作系统, 故障描述, 以及故障重现方法等. -------------------------------------------------------------------------------- 9. 更新历史 ver 1.00 ... 日文版 (1996/08/19) ver 1.31 ... 英文版/日文版 (1997/09/01) ver 2.00 ... 英文版/日文版 (2002/11/19) 支持文件/文件夹传送 支持通信数据加密 ver 2.03 ... Bug 修正 (文件传送引起缓冲溢出) 广播设置支持主机地址(FQDN)解析 ver 2.04 ... 增加绑定网卡(IP)功能 ver 2.05 ... Bug 修正 (2.04版当激活发送/接收消息窗口时,无法注销/关闭系统) ver 2.06 ... 很小的调整

2005-12-14

一个书库的小偷程序

可以定制www.mengdong.com 上面的所有子栏目. 可以单独使用,也可以放入你们的 页面。 风格可以通过demo.css定制 也可以当作合作伙伴定制

2005-12-20

玄武饭店信息管理系统

玄武饭店信息管理系统 代码较为全面。

2005-12-23

计算机投标书格式(范本)

word文档格式 投标书格式 投 标 书 致:________________________________   根据贵方为___________________________________项目招标采购货物及服务的投标邀请_____________________ (招标编号),签字代表______________________(全名、职务)经正式授权并代表投标人____________________(投标方名称、地址)提交下述文件正本一份和副本一式____份。 (1) 开标一览表 (2) 投标价格表 (3) 货物简要说明一览表 (4) 按投标须知第14、15条要求提供的全部文件 (5) 资格证明文件 (6) 投标保证金,金额为人民币____________________元。 据此函,签字代表宣布同意如下: 1.所附投标报价表中规定的应提供和交付的货物投标总价为人民币____________________元。 2.投标人将按招标文件的规定履行合同责任和义务。 3.投标人已详细审查全部招标文件,包括修改文件(如需要修改)以及全部参考资料和有关附 详细内容请下载

2005-12-23

Apache HTTP服务器 管理员手册

2005-12-06

多级联动下拉选择框,动态获取下一级

多级联动下拉选择框,动态获取下一级,每一级数据为XML,可支持无限级(浏览器端需要Microsoft.XMLDOM支持) 项目需要,一个材料类别表,三级,总共有7000多条记录,如果一次获取会很慢的,所以就是用了动态读取,每次就读一级,且服务器端使用了缓存,效率还不错。

2006-01-05

PHP设计模式(chm版)

导言 当你在不断的试图从你的应用程序中发现新的特征时,你是否发现你提出的解决方法和一些以前你已经实现的东西是如此的类似呢?如果你是一个程序员(即使你才 开始很短的时间),你都可能回答“是”。这看起来就是你使用了一些以前的代码来解决软件开发过程中新发现的问题了。你可能已经认识到:你的解决方法是基本 原理,是一个不仅仅是你而且是所有专业开发者都能广泛重复应用的方法。 事实上,许多程序问题都不断的反复的遇到,而且许多用来解决这些问题的基本方法(或者说是设计模式)都已经浮现出来。设计模式就是一个教你如何利用真实可靠的设计来组织你的代码的模板。 设计模式历史 “设计模式”这个术语最初被设计用于建筑学领域。Christopher Alexander 在他1977的著作“A Pattern Language :Towns/Building/Construction”里面描述了一些常见的建筑学设计问题,并解释了如何用这些已有的,著名的模式集合来开始全新 的有效的设计。Alexander的观点被很好的转化到软件开发上来,并且长期的合意的用原有的组件来构造新的解决方案。 所有的设计模式都有一些常用的特性:一个标识(a name),一个问题陈述(a problem statement)和一个解决方案(a solution)。 1、一个设计模式的标识是重要的,因为它会让其他的程序员不用进行太深入的学习就能立刻理解你的代码的目的(至少通过这个标识程序员会很熟悉这个模式)。? 2、问题描述是用来说明这个模式的应用的领域。? 3、解决方案描述了这个模型的执行。一个好的设计模式的论述应该覆盖使用这个模型的优点和缺点。? 一个模式是解决特定问题的有效方法。一个设计模式不是一个库(能在你的项目中直接包含和使用的代码库)而是一个用来组织你的代码的模板。事实上,一个代码库和一个设计模式在应用上是有很多不同的。 比如,你从店铺里面买的一件衬衫是一个代码库,它的颜色,样式和大小都由设计师和厂商决定,但它满足了你的需求。 然而,如果店里面没有什么衣服适合你,那你就能自己创建自己的衬衫(设计它的形状,选择布料,然后裁缝在一起)。但是如果你不是一个裁缝,你可能会发现自 己很容易的去找一个合适的模式然后按着这个模式去设计自己的衬衫。使用一个模型,你可以在更少的时间内得到一个熟练设计的衬衫。 回到讨论软件上来,一个数据提取层或者一个CMS(content management system)就是一个库——它是先前设计好而且已经编码好了的,如果它能准确的满足你的需要那它就是一个好的选择。但如果你正在读这本书,可能你会发现 库存的(原有的)解决方案并不是总是对你有效。至今你知道什么是你所要的,而且你能够实现它,你仅仅需要一个模型来引导你。 最后一个想法:就象一个裁缝模型,一个设计本身而言是没有什么用处的。毕竟,你不可能穿一个服装模型——它仅仅是由很薄的纸拼凑起来的。类似的,一个软件设计模型也仅仅只是一个引导。它必须根据程序设计语言和你的应用程序的特点和要求而特别的设计。 本书的目标 本书的目的不是为了全面的介绍各种类别的软件设计模式,也不是为了发展一个新的设计模式或者术语,而是为了突出介绍一些已有的著名的设计模式。这本书的 独特之处在于介绍了一些我认为对开发动态WEB应用程序很有帮助的设计模式,而且用PHP语言显示了如何实现这些设计模式。 面对对象编程OOP 这本书一个优点就是所有的观点都是基于OOP这种很自然的设计模式,并且用OOP来实现。

2006-05-22

web下的listview控件

尝试着写web下的listview控件,listview一般有四种显示模式——平铺、图标、列表和详细信息。这些显示模式唯一的共同点就是数据是相同的,显示效果完全不一样。这时候xml的优势就完全体现出来了。 第一步,就是建立一个自定义格式的xml,用来保存listview数据 第二步,xsl可以解析xml生成html,所以就针对listview的每一种显示效果设计了一个对应的xsl。这样前面定义的xml数据和不同的xsl一起就可以显示出不同的效果。 第三步,htc在开发web控件时,非常灵活和功能强大,可以采用客户端脚本如js,可以对控件进行封装,使之有自己的属性、方法和事件等。利用htc封装的listview控件中对外有两个属性CfgXMLSrc(配置文件,设置listview的每一种显示模式对应的xsl文件路径等信息)和View(listview的显示模式),在htc中根据listview的View属性来选择不同的xsl文件和xml数据文件生成html,并输出。 这样就可以通过改变listview控件的view属性来切换listview的不同显示效果。 在线演示 打包下载 以前写换皮肤的控件,都是通过更换css和图片路径来做的(可以看看http://www.stedy.com),局限性很大,例如toolbar,在winxp和win2000下差别很大,只靠通过换css和图片路径无法应付这种情况。通过开发listview的经验,从中悟到了一种更好的开发换皮肤的web控件的模式: 首先将控件的相关数据用xml描述出来,对于每一种Theme(皮肤/主题样式),有一个相关的配置文件,配置文件中记载了该控件所用到的xsl、css、图片路径、htc等信息。在控件相关的htc中,根据Theme属性组合这些。从而可以灵活的应付各种情况。 例如刚才说的toolbar,假如入我们有三种风格:winxp蓝色、winxp银色和windows经典,前面两种基本差不多,只是样式和图片不一样,而后面一种和前面的两种差别比较大。那么我们需要写两个xsl,三个css文件,三个图片文件夹,组合一下就可以生成这三种风格的toolbar了。 这种控件开发模式会慢慢流行起来并在asp.net控件中发挥重要作用的

2006-01-05

AJAX开发简略(附源代码)

AJAX开发简略... 1 一、AJAX定义... 3 二、现状与需要解决的问题... 3 三、为什么使用AJAX. 4 四、谁在使用AJAX. 6 五、用AJAX改进你的设计... 6 例子1:数据校验... 7 例子2:按需取数据—级联菜单... 7 例子3:读取外部数据... 7 六、AJAX的缺陷... 7 七、AJAX开发... 8 7.1、AJAX应用到的技术... 8 A、XMLHttpRequest对象... 8 B、Javascript. 9 C、DOM. 9 D、XML. 9 7.2、AJAX开发框架... 9 A、初始化对象并发出XMLHttpRequest请求... 9 B、指定响应处理函数... 10 C、发出HTTP请求... 10 D、处理服务器返回的信息... 11 E、一个初步的开发框架... 11 7.3、简单的示例... 13 A、数据校验... 13 B、级联菜单... 14 参考文章:... 16 在使用浏览器浏览网页的时候,当页面刷新很慢的时候,你的浏览器在干什么?你的屏幕内容是什么?是的,你的浏览器在等待刷新,而你的屏幕内容是一片空白,而你在屏幕前苦苦的等待浏览器的响应。开发人员为了克服这种尴尬的局面,不得不在每一个可能需要长时间等待响应的页面上增加一个DIV,告诉用户“系统正在处理您的请求,请稍候……”。 现在,有一种越来越流行越热的“老”技术,可以彻底改变这种窘迫的局面。那就是AJAX。如今,随着Gmail、Google-maps的应用和各种浏览器的支持,AJAX正逐渐吸引全世界的眼球。

2006-01-04

WAPM综合网络服务器系统v2.0.3 正式版本 [绿色的]

WAPM是综合网络服务器系统。 它包含了以下组件: Apache2,是互联网最最最流行的WEB服务软件,用以提供基本的WEB服务功能,同时支持SSL,GZIP,LIC(IP同时连接数限制)功能; PHP4,PHP5,是互联网最最最流行的动态网页语言,用以提供PHP语言的网络应用程序开发,同时支持ZendOptimizer优化功能和Zend加密功能,或者Turck MMCahe对PHP的加速、优化、加密、动态缓存功能; Tomcat4,用以提供互联网最最最热门的JSP(JavaServer Pages)和Servlet(Java Servlet)的服务解析。 MySQL4,用以提供互联网最最最流行的SQL数据库功能。 为什么选择WAPM? ----------- 解压不用任何配置,就可以安装运行 强大的WEB服务器功能,可配置性强,可管理性高 独创的全中文虚拟主机配置系统 全Unix路径设置,为将来升级迁移预留接口 所有软件采用开放源代码阵营的软件 支持最流行的技术 专业的技术支持

2006-01-24

CakePHP :: Ajax Demo

This is a simple demo of some of the AJAX helpers now available in CAKE. These helpers are directly modeled on Ruby On Rails. In fact, they were shamelessly ported from rails almost verbatim. You can also see some of the amazing effects available through the Prototype javascript library. This is a demo not an application. Obviously this uses far too much AJAX in nonsensical ways. 很不错的基于php+ajax的例子

2006-01-04

DotArticle 文章管理系统 (asp版) 0.1版

仿照sharepoint,已实现核心功能: 如果要使用sql server版,请执行data目录下的dotarticle.sql,并适当修改inc/data.asp中的sql连接即可

2006-01-05

系统分析师考试论文案例集(第二辑)

论文一 论Java技术在因特网平台上的应用—通信服务平台的应用 论文二 论Java技术在因特网平台上的应用——银行业的应用 论文三 论改进Web服务器性能的有关技术—银行业的应用 论文四 论改进Web服务器性能的有关技本——数字图书馆类的应用 论文五 论实时控制系统与企业信息系统的集成——通信业应用 论文六 论实时控制系统与企业信息系统的集成——工业自动化改造的应用 论文七 论实时控制系统与企业信息系统的集成——工业控制的常规应用

2006-01-04

无限菜单之 xml+popup 版(IE5.5+)

在IE5.5+中开始支持的Popup窗口有很多很特别的特性: Popup窗口可以超出浏览器窗口区域; 可以不用担心被下拉框、flash、Iframe等这些东西遮挡; 一个Popup窗口打开后,当在它的区域以外点击或者另一个Popup窗口被打开时都会自动关闭; Popup窗口是没有焦点的; 用户不能改变Popup窗口大小; Popup窗口中的内容是不能被选择的; ...... 因为这些特征,Popup窗口制作的菜单比起传统的div(层)实现的菜单有着得天独厚的优势,不仅效果会非常好,而且代码也会是非常少的,只是对于实现起来却有几个需要解决的棘手问题:多个Popup共存的问题、如何递归生成菜单、如何控制Popup的显示隐藏…… 要用Popup制作菜单一个最重要的问题就是要解决多个Popup共存的问题,Msdn上的描述是:“一个Popup窗口打开后,当另一个Popup窗口被打开时就会自动关闭”。我本来一直以为Popup窗口是不可以多个共存的,不过偶然从51js上知道:父Popup窗口可以创建子Popup窗口,子Popup窗口又可以创建子Popup窗口,这样就可以同时存在一个Popup窗口家族,当父Popup窗口关闭,所有的子孙窗口都会关闭。这点恰好可以运用在菜单中——父菜单关闭子菜单一起关闭,省去很多繁琐的判断。 最开始,我写了一个简单的两层的Popup右键菜单,为此专门写了一个根据级数生成Popup窗口家族的递归方法: var pops = new Array(); // 用来存储Popup窗口家族的数组 function CreatePopup(degree) { if (degree < 0) // 层数不能小于0 return null; if (pops[degree] != null) //如果已经存在则不需创建 return pops[degree]; if (degree == 0) pops[0] = window.createPopup(); //创建最顶层Popup窗口 else{ if (pops[degree - 1] == null) pops[degree - 1] = CreatePopup(degree - 1) //递归回溯一层一层开始创建 pops[degree] = pops[degree - 1].document.parentWindow.createPopup(); //从父Popup窗口创建子Popup窗口 } pops[degree].document.body.setAttribute("degree", degree); return pops[degree]; } CreatePopup(1); //创建一个2层的Popup家族 这个方法可以解决多个Popup共存的问题,只是如果要使用这个方法来实现无限级菜单代码恐怕就比较繁琐了。这个例子,只是为我验证了无限级Popup窗口共存的可能,并没有继续走下去,因为我有了更好的思路。 Xml真是好东西,在Web控件中,可以得到灵活的运用(在我的上篇随笔《xml+xsl+htc,web控件开发的理想组合》中,已经简单提到了xml+xsl+htc的理想组合),在这里也不例外,先用Xml来定义好菜单的数据menu.xml: <?xml version="1.0" encoding="GB2312"?> <Menu> <MenuItem Text="菜单1"> <MenuItem Text="菜单1子菜单"/> </MenuItem> <MenuItem Text="菜单2"/> </Menu> 通过Xml,可以很方便直观的定义菜单数据。 菜单数据已经定义好了,现在问题就是如何来把这些xml数据变成Popup菜单?!在传统的用div(层)来实现的菜单,一般都是一次性将所有级菜单数据生成HTML,放在各个层中,然后动态在制定位置显示隐藏这些层来实现模拟菜单的效果,在这里当然也可以这么做。回想一下菜单的特征:每次显示一级菜单,如果该级菜单中某菜单项中有子菜单,当鼠标经过或者点击该菜单项时弹出下级子菜单,这是一个递归的过程。如果我们可以:每次显示一级xml的内容,如果该级xml中某节点有子节点,当鼠标经过该节点时读取下级xml的内容,这也是一个递归的过程,而且恰好和菜单的显示过程是一一对应的。 既然大胆假设了一把,那么就来小心求证一下:首先,用xsl来实现解析一级xml很容易搞定,使用xsl:for-each遍历生成子菜单,并且,如果子菜单中还有子xml数据,将这些子xml数据存在子菜单对应的数据岛中,以备后面处理鼠标经过或点击菜单项时用到。下面是Menu.xsl用来生成子菜单的部分: <!-- 遍历子菜单 --> <xsl:for-each select="MenuItem"> <tr height="18" onmouseover="ItemOver(this)" onmouseout="ItemOut(this);" onclick="ItemClick(this)"> <td width="17" align="center"> <IMG SRC="images/dot1.gif" WIDTH="6" HEIGHT="6" BORDER="0" ALT=""/> </td> <td> <xsl:value-of select="@Text" /> <xsl:if test="count(MenuItem) > 0"> <!-- 这里用来存储子菜单的xml数据 --> <xml> <xsl:copy-of select="."/> </xml> </xsl:if> </td> <td width="20" align="right" valign="top" style="padding-right: 6px; padding-top:4px;"> <!-- 如果有子菜单则显示箭头 --> <xsl:if test="count(MenuItem) > 0"> <img src="images/arrowR.gif"/> </xsl:if> </td> </tr> </xsl:for-each> 现在就是解决鼠标经过菜单项时,如果有子菜单则解析子菜单数据,并使用子Popup窗口显示子菜单数据,刚才我们存的数据岛这时候就可以派上用场了。在xsl中,需要用到一些客户端脚本来辅助完成了 // 创建当前窗体(可以是IE窗体也可以是Popup窗体)的Popup对象 // 这个Popup对象就是用来存储子菜单数据的 var oPopup = document.parentWindow.createPopup(); // 装载xsl var stylesheet = new ActiveXObject("Microsoft.XMLDOM"); stylesheet.async = false; stylesheet.load( "menu.xsl" ); // 鼠标经过菜单项 function ItemOver(obj) { // 隐藏已经打开的菜单项 if (preObj != null) { if (preObj == obj) return; oPopup.hide(); // 要清空原Popup中的数据——document.write()方法是接着原来的内容往里面写,所以如果不清空会出现重复数据 oPopup = document.parentWindow.createPopup(); // 恢复前一个菜单项的状态 ItemNormal(preObj); preObj = null; } obj.className='PopMenuItemOver'; if (obj.cells(2).children.length > 0) //有子菜单 { obj.cells(2).children(0).src = "images/ArrowRHighlight.gif"; // 获取子菜单xml数据 var subMenuData = obj.all.tags("xml")(0).XMLDocument; // 根据子菜单xml数据和当前xsl文档生成HTML var sHtml = subMenuData.transformNode(stylesheet); // 将解析出来的HTML全部输出到Popup中,在Popup中,又可以利用这些脚本再Popup…… oPopup.document.write(sHtml); // 计算popup内容的实际宽度高度 oPopup.show(0, 0, 1, 1, obj); var width = oPopup.document.body.scrollWidth; var height = oPopup.document.body.scrollHeight; oPopup.hide(); // 显示菜单 oPopup.show(obj.offsetWidth, 0, width, height, obj); preObj = obj; } } // 鼠标移出菜单项 function ItemOut(obj) { if (oPopup.isOpen && preObj == obj) // 如果子菜单被打开则跳过 return; ItemNormal(obj); } // 恢复到菜单项的默认状态 function ItemNormal(obj) { obj.className='PopMenuItem'; if (obj.cells(2).children.length > 0) { obj.cells(2).children(0).src = "images/ArrowR.gif"; } } 这样:使用menu.xsl解析一级xml的内容生成一级菜单,如果该级xml中某节点有子节点,当鼠标经过该节点时,创建当前窗口/Popup窗口的子Popup窗口,使用menu.xsl解析子节点中xml的内容并输出显示到子Popup中,递归,即可通过Popup显示所有子菜单。 作为一个菜单来讲,这个例子还有很多要完善的地方(当我再结合htc时它绝对是一个非常棒的菜单控件),但是这个例子已经完整地实现了一个xml结合xsl递归生成无限Popup菜单的例子,这个简洁的代码再次印证了xml+xsl+htc的理想组合。

2006-01-05

左右侧的树选择节点功能

从左侧的树选择节点,右侧将选择的节点按照树形显示。 如果父节点选择,则子节点默认全部选中,所以在右侧默认不显示子节点 写的比较仓促,左边的树是在微软的基础上改进的,右边的树是我以前写的一个根据xml+xsl生成树的小程序 选择移除操作都是对xmldom进行操作,操作完了重新加载这个xmldom

2006-01-05

从A空间直接下载文件到B空间—RGD 1.5

 RGD 是一个下载工具,但是它不是应用于你的个人电脑的!   RGD 可以下载别的网站提供的东西直接到你的空间中,不用下载到本地然后再上传到自己的空间中,也就是是从A空间到B空间(可以是不同服务器上的,也可以使同一台服务器上的), 举个例子: shou.com提供下载一个软件 sohu.com/soft111.rar , 你可以将这个下载的软件直接下载到自己的空间里面的某个你设定的目录。这么说应该可以理解!   RGD 可以节省你的下载时间,如果你下载的东西在国外的空间上,而你自己的也是国外空间,那么它可以节省你多多一半的下载再上传的时间。假设你使用了一台没有按照FTP软件的电脑,那么有了RGD ,你就方便了,打开自己的装有RGD 的空间,输入你想要下载的软件(或其它)的下载地址连接,把你下载的东西先放在自己空间里保存好!   RGD 可以添加注释内容; 可以直接将下载的文件分割并存储; 可以发送电子邮件到你指定的邮箱;可以设置并使用代理服务器下载;可以指定下载保存目录。 它在线编辑功能: 可以批量更改文件名;可以批量分割文件;可以批量发送到电子邮件;可以批量删除! 注意:    1) 你的空间必须支持PHP (不需要MySQL), 如果是 Linux主机, 你所设定的下载目录的属性一定要改成777, windows主机不需要改!   2) 这是有一个管理工具,不是随便开放给每个人使用的,除非是你的好朋友!当然我的演示也除外!所以请更改下载以后的文件名称,改一个你能记住的,默认的是 a2b.php , 下载目录中的index.html不要删除或者你可以换一个别的内容的页面,这是为了防止别人看到你网页目录下内容的。   3) 如果你用 RGD 上传东西到你的空间里面了,最好 删除或重命名的时候也用 RGD 来操作,因为程序在空间里面生成了一个列表文件(files.lst), 如果你在FTP上删除或重命名文件了,那么列表示没有变化的。那么在RGD 里看到的内容要和实际的文件不一样了。

2006-01-04

skype开发应用程序接口文件(API)中文版

skype的API的详细说明,示范代码等相关资料,PDF文件的形式。 skype魔法表情就是用skype API开发的一个有趣的skype插件

2006-01-10

Struts+Spring+Hibernate实现上传下载

基于struts、spring、hibernate的上传下载程序

2006-01-04

AjaxHelper的企业门户网站构架示例

采用asp基于AjaxHelper的企业门户网站构架示例

2006-01-04

数字信号处理程序

里面有FIR IIR,和傅立叶变换,FFT等功能。

2005-12-31

拖动效果(ajax+php)示例

采用php+ajax实现的拖动效果例子程序

2006-01-04

拖动条(ajax+php)示例

采用ajax+php实现的拖动条示例

2006-01-04

sajax-0.10

WELCOME TO SAJAX ---------------- Sajax is a cross-platform, cross-browser web scripting toolkit that makes it easy to expose functions in your code to JavaScript. For more information about Sajax, please see the homepage: http://www.modernmethod.com/sajax/ In this archive you will find a folder for each platform that is currently supported. Please see individual documentation in each folder for specific errata. 下载三,为扩展名tgz格式的下载包

2006-01-04

用户名检测(ajax+php)

采用ajax+php检测用户的示例程序

2006-01-04

WebBaker_0.10.0_dev

WebBaker is a web build utility for CakePHP Framework. It can help build the necessary CakePHP MVC files. To match current CakePHP release, it's current version is 0.10.0_dev. Installation Copy 'app' and 'vendors' directories to your CakePHP root directory. Chmod app/models, app/controllers, and app/views to 0777. Launch http://localhost/cake/bakers or http://localhost/bakers (depending on your CakePHP installation).

2006-01-04

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除