我正在使用 https://dweet.io/ - 这个概念是您可以将一些字段/值发送/发布到 dweet.io,您可以看到直接在那里发布的这些值,甚至可以看到这些数据作为https://freeboard.io/中的图形仪表。前者无需注册;数据直接发布。
带有
curl
的示例:
$curl 'https://dweet.io/dweet/for/:kpv1?volt1=622&volt2=624&volt3=600'
#response:
{"this":"succeeded","by":"dweeting","the":"dweet","with":{"thing":":kpv1","created":"2023-11-05T19:03:17.892Z","content":{"volt1":622,"volt2":624,"volt3":600},"transaction":"98967dcf-168d-4c78-a190-9476ff95e9cd"}}
如果我在浏览器中输入 URL
https://dweet.io/dweet/for/:kpv1?volt1=622&volt2=624&volt3=600
,也可以获得相同的结果。访问 https://dweet.io/follow/:kpv1 显示之前发布的数据。
我想通过 Free Pascal/Lazarus 使用简单的后期解决方案来实现此功能。我已经在简单的 GUI 表单中尝试了下面的代码,其中包含
TEdit
和 TButton
,但是当我按下按钮时没有任何反应... dweet.io 未更新,我的 Edit1.Text
仍然为空。而且我什么也没有stderr
。
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, opensslsockets, fphttpclient;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
URL, S : String;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
URL := 'https://dweet.io/dweet/for/:kpv1?volt1=922&volt2=924&volt3=900';
S := TFPCustomHTTPClient.SimplePost(URL);
Writeln(stderr, S);
Edit1.Text:=S;
end;
有什么想法我错过了......?
好吧,问题是我在
dweet.io中使用的
"thing"
名称。对于名为 "thing"
的 :kpv1
,代码会中断。如果我将名称更改为 kpv1
(删除 :
字符),则代码可以正常工作。因此,当从 kpv1
中删除冒号时,这两行就可以正常工作:
URL := 'https://dweet.io/dweet/for/kpv1?volt1=922&volt2=924&volt3=900';
S := TFPCustomHTTPClient.SimplePost(URL);
// response received in Edit1.Text:
// {"this":"succeeded","by":"dweeting","the":"dweet","with":{"thing":"kpv1","created":"2023-11-05T20:09:47.833Z","content":{"volt1":922,"volt2":924,"volt3":900},"transaction":"7177dc55-a174-4edd-b88d-fd64cc4dad9f"}}
// Values posted to dweet.io for kpv1 can be visualized in address https://dweet.io/follow/kpv1
问题是你不尊重 HTTP 中的 URI/URL 的构造方式 - 其中 冒号是根据 RFC 3986 的保留字符并且需要 百分比编码为
%3A
是路径、查询或片段/锚点的一部分。同样的规则也适用于其他选定的字符(特别是如果您想表达空格
或斜杠 /
或与号 &
或问号 ?
等内容)。
所以整个补救措施应该是:
URL := 'https://dweet.io/dweet/for/%3Akpv1?volt1=922&volt2=924&volt3=900';
...与 FreePascal 和 dweet.io 无关 - 它适用于 HTTP 知识。我将在您的问题中添加相应的标签。
httpprotocol.HTTPEncode()
在实现方面看起来很正常,所以你通常可以这样做:
uses
httpprotocol;
begin
URL:= 'https://dweet.io/dweet/for/' // protocol + domain + path
+ HTTPEncode( ':Akpv1' ) // resource
+ '?volt1='+ HTTPEncode( '922' ) // first parameter
+ '&volt2='+ HTTPEncode( '924' ) // second parameter
+ '&volt3='+ HTTPEncode( '900' ) // third parameter
;
注意:编码 URL 的组成部分,而不是一般的整个 URL。