Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Http_request help

Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-17-2009 09:03
Hi everyone,

I am building an avatar tracker that sends data to my server.

It works perfectly when the tracker detects only one avatar. However, the for loop I made doesnt seem to work when it picks up multiples avs.

When multiple avs are detected, the first avs data is sent perfectly fine... but then it gets stuck and doesnt send any more data.

What's worse is, this gets the script stuck because it cant return to the default state until all http_responses have been received... so it stops tracking avatars.

So, does anyone know how to send multiple http_requests to a server and successfully receive an http_response for each?

Thanks!
Pete Olihenge
Registered User
Join date: 9 Nov 2009
Posts: 315
12-17-2009 12:13
You can either send a batch of HTTP requests from a loop, and keep a list of the request IDs, or you can send a new HTTP request from the http_response event after you've processed the data from that for the previous request.

Note that llHTTPRequest is subject to throttling that limits you to about 1 per second.
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-17-2009 12:32
I already have it set up to send them all with a loop.

Should I set a 1 second timer at the end of the loop so it delays the requests?
Pete Olihenge
Registered User
Join date: 9 Nov 2009
Posts: 315
12-17-2009 12:51
There are so many things that could be going wrong with your send loop it's impossible to list them all. Have you checked if the requests are actually being sent? (Put an llOwnerSay immediately before or after the llHTTPRequest call). Are you keeping a list of the request ids, or are you assigning them all to the same variable? Have you forgetten to increment the loop counter? Have you accidentally used an assignment "=" instead of a comparison "==" in an "if" test on the loop counter? Etc...

If you are likely to run into the throttle limit, and it's important not to lose any of the HTTP requests, then you will have to consider using the timer loop to either drip-feed the requests at about 1 per second or to send batches of up to 25 every 20 seconds. WARNING: I haven't any actual experience of scripting to circumvent LSL throttles - this is a topic for someone else to comment on.
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-17-2009 13:40
I haven't verified that all the requests are being sent... I'll check that and then reply.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-17-2009 14:40
you are much better off to send the requests one at a time. requesting the first one from outside the dataserver event, and the rest from it's end....

brief psuedo-example
CODE

key gKeyQID;
integer gIntCnt;
list gLstAvKeys = [put your keys here];

default{
state_entry(){
gIntCnt = (gLstAvKeys != [])
gKeyQID = llRequestAgentData( llList2Key( gLstAvKeys, --gIntCnt ), DATA_ONLINE );
}

dataserver( key vKeyQuery, string Data ){
if (gKeyQID == vKeyQuery){ //-- this line prevents outside request from being processed
//-- do what you want with the string
//-- send the data out via http
if (gIntCnt){
gKeyQID = llRequestAgentData( llList2Key( gLstAvKeys, --gIntCnt ), DATA_ONLINE );
}
}
}
}
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-17-2009 19:06
Hmmm looks interesting. Thanks for providing that...

what do you mean by "insert keys here"?

Could you perhaps briefly comment the code so I know what each line does. I am not familiar with several of those functions.

Thanks for all your help!
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-17-2009 22:19
CODE

key gKeyQID; //-- stores the current request ID
integer gIntCnt; //-- a target counter for your list of keys
list gLstAvKeys = ["a822ff2b-ff02-461d-b45d-dcd10a2de0c2", ""a822ff2b-ff02-461d-b45d-dcd10a2de0c2"]; //-- etc (no I don't know if that's a valid av key)

default{
state_entry(){
gIntCnt = (gLstAvKeys != []); //-- cheap trick to get the list length
//-- grab the last key in the list, and request their online status
gKeyQID = llRequestAgentData( llList2Key( gLstAvKeys, --gIntCnt ), DATA_ONLINE );
}

dataserver( key vKeyQuery, string Data ){
if (gKeyQID == vKeyQuery){ //-- make sure this is our request and not a different one
//-- do what you want with the string
//-- send the data out via http
if (gIntCnt){ //-- make sure there are more keys to check
//-- make a new request
gKeyQID = llRequestAgentData( llList2Key( gLstAvKeys, --gIntCnt ), DATA_ONLINE );
}
}
}
}

llList2Key( gLstAvKeys, --gIntCnt )
grabs the list item at specified index, and returns it as a key
--gIntCnt
subtract one from gIntCnt and then use it.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-19-2009 17:45
Hmmm... so am I stuck to using just the basic functions that can utilize the dataserver function?

I want to collect a lot more data than just the few variables that trigger the dataserver.

It might be easier to just stick with the httprequest version. How would I go about throttling the requests so they can be handled properly?
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-19-2009 17:58
From: Sherman Gustafson
Hmmm... so am I stuck to using just the basic functions that can utilize the dataserver function?

uh, no.... but the discussion was online status, so I just outlined that part

From: someone
I want to collect a lot more data than just the few variables that trigger the dataserver.

you can still, you can even call them from the dataserver event in the example I outlined if you like.

From: someone
It might be easier to just stick with the httprequest version. How would I go about throttling the requests so they can be handled properly?

guess it depends on what data you are requesting and from where, but the same concept works for http requests, by only requesting the next one from within the return event, it self throttles to the speed of the returns.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-19-2009 20:53
Do you mind taking a loot at the code and see if you can spot any problems? Also, now you'll know what data I'm trying to collect.

CODE

//Accounts for overlap of the 4 sensors... leave these values as they are
float x_min = 0;
float x_max = 128;
float y_min = 128;
float y_max = 256;

float scanDistance = 96.0;
float scanRadius = PI; //definitely leave alone
float scanTimeout = 60.0;

//Lists of information about agents
list agentKeyList;
list agentNameList;
list bornOnList;
list agentInfoList;
list agentPositionX;
list agentPositionY;
list agentDate;
list agentRotation;
list agentVelocity;

//Temp variable for current agent list index
integer agent;

//Count of http requests waiting to return
integer httpCount;

//List used for testing if we've seen this person before
list response;

default
{
state_entry()
{
//This puts text over the object indicating that it's a slogbase beacon.
//You can safely remove this line.
llSetText("SL Track Touch Version2", <1,1,1>, 1.0);
llSensorRepeat("", NULL_KEY, AGENT, scanDistance, (2*(scanRadius)), scanTimeout);
}

//When clicked... do this

//Custom start function
sensor(integer total_number)
{

//Temp variable
key agentKey;

vector tempPos;

//is in group?
integer i;

for (i = 0; i < total_number; i++)
{
if (llSameGroup(llDetectedKey(i)))

{

//Blank out lists
agentKeyList = [];
agentNameList = [];
agentInfoList = [];
agentPositionX = [];
agentPositionY = [];
agentDate = [];
agentRotation = [];
agentVelocity = [];
bornOnList = [];

llSetText("Slogbase Beacon (scanning)", <1,1,1>, 1.0);

//Build lists
for(agent=0; agent < total_number; ++agent)
{
tempPos = llDetectedPos(agent);
agentKeyList += [llDetectedKey(agent)];
agentNameList += [llKey2Name(llDetectedKey(agent))];
agentInfoList += [llGetAgentInfo(llDetectedKey(agent))];
agentPositionX += [(integer)tempPos.x];
agentPositionY += [(integer)tempPos.y];
agentDate += llGetDate();
agentRotation += [llDetectedRot(agent)];
agentVelocity += [llDetectedVel(agent)];
}

//llDetectedPos(agent)
//Jump into state for fetching born-on dates
agent = 0;
state getBornOn;


}
//if not in group, stop them in their tracks
else {
llSay(0, wrongGroupWarning);}
}
}

}

state getBornOn
{
state_entry()
{
//Are we done?
if(agent == llGetListLength(agentKeyList))
{
state report;
}

//Request born-on date for this agent
llRequestAgentData(llList2Key(agentKeyList, agent), DATA_BORN);
}

dataserver(key queryid, string data)
{
//Got the born-on date, save it and move to next request
bornOnList += [data];
++agent;
state continueBornOn;
}
}

//We need this state simply so that we can loop over requests for born-on date.
state continueBornOn
{
state_entry()
{
state getBornOn;
}
}

//All data is ready. This state sends it to the Web service.
state report
{
state_entry()
{
//Temporary variables
string body;
list infoSummary;
integer agentInfo;




//Set the count of agents so that we can figure out when we've
//completed sending out each request.
httpCount = llGetListLength(agentKeyList);

//Turn the agent info flags into text.
for(agent = 0; agent < llGetListLength(agentKeyList); ++agent)
{
body = "";
infoSummary = [];
agentInfo = llList2Integer(agentInfoList, agent);

list timestamp = llParseString2List( llGetTimestamp(), ["T",":","Z"] , [] );
string hour = llList2String( timestamp, 1 );
string minute = llList2String( timestamp, 2 );
string second = llList2String( timestamp, 3 );

integer checkX = llList2Integer(agentPositionX,agent);
integer checkY = llList2Integer(agentPositionY,agent);



if(agentInfo & AGENT_ALWAYS_RUN)
{
infoSummary += ["AGENT_ALWAYS_RUN"];
}
if(agentInfo & AGENT_ATTACHMENTS)
{
infoSummary += ["AGENT_ATTACHMENTS"];
}
if(agentInfo & AGENT_AWAY)
{
infoSummary += ["AGENT_AWAY"];
}
if(agentInfo & AGENT_BUSY)
{
infoSummary += ["AGENT_BUSY"];
}
if(agentInfo & AGENT_CROUCHING)
{
infoSummary += ["AGENT_CROUCHING"];
}
if(agentInfo & AGENT_FLYING)
{
infoSummary += ["AGENT_FLYING"];
}
if(agentInfo & AGENT_IN_AIR)
{
infoSummary += ["AGENT_IN_AIR"];
}
if(agentInfo & AGENT_MOUSELOOK)
{
infoSummary += ["AGENT_MOUSELOOK"];
}
if(agentInfo & AGENT_ON_OBJECT)
{
infoSummary += ["AGENT_ON_OBJECT"];
}
if(agentInfo & AGENT_SCRIPTED)
{
infoSummary += ["AGENT_SCRIPTED"];
}
if(agentInfo & AGENT_SITTING)
{
infoSummary += ["AGENT_SITTING"];
}
if(agentInfo & AGENT_TYPING)
{
infoSummary += ["AGENT_TYPING"];
}
if(agentInfo & AGENT_WALKING)
{
infoSummary += ["AGENT_WALKING"];
}

//Build the HTTP post variables
body = "name=" + llEscapeURL(llList2String(agentNameList, agent)) +
"&time=" + hour + ":" + minute + ":" + second +
"&born=" + llEscapeURL(llList2String(bornOnList, agent)) +
"&info=" + llEscapeURL(llList2CSV(infoSummary)) +
"&posx=" + (string)llList2Integer(agentPositionX,agent) +
"&posy=" + (string)llList2Integer(agentPositionY,agent) +
"&date=" + llEscapeURL(llList2CSV(agentDate)) +
"&objectclicked=" + llGetObjectName();


llSay(0, "Send: " +

"&name=" + llEscapeURL(llList2String(agentNameList, agent)) + "\n" +
"&time=" + hour + ":" + minute + ":" + second + "\n" +
"&born=" + llEscapeURL(llList2String(bornOnList, agent)) + "\n" +
"&info=" + llEscapeURL(llList2CSV(infoSummary)) + "\n" +
"&posx=" + llEscapeURL(llList2String(agentPositionX, agent)) + "\n" +
"&posy=" + llEscapeURL(llList2String(agentPositionY, agent)) + "\n" +
"&date=" + llEscapeURL(llList2CSV(agentDate)) + "\n" +
"&objectclicked=" + llGetObjectName()



);






llHTTPRequest("http://www.www.com/track.php",
[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],
body);

}
}


http_response(key request_id, integer status, list metadata, string body)
{


//If it seems like we got all the responses back, then go back to waiting
--httpCount;
if(httpCount == 0)
{
state default;
}
}
}

Paladin Pinion
The other one of 10
Join date: 3 Aug 2007
Posts: 191
12-19-2009 22:49
From: Void Singer

gIntCnt = (gLstAvKeys == []); //-- cheap trick to get the list length

Can you explain how this works? It looks like it should only produce a boolean value.
_____________________
Mote Particle Script Generator - easier and faster than any HUD
Also: Paladin's Sunbeam. Up at dawn, gone by dusk, day and night sounds, fully configurable
See more at: www.paladinpinion.com
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-20-2009 00:27
From: Paladin Pinion
Can you explain how this works? It looks like it should only produce a boolean value.

whoops, good catch, corrected above, that should've read != rather than == (which still looks like it should return a boolean but when it's used to compare lists, it actually compares their length and returns the difference, specifically (listA != listB) -> (lengthListA - lengthListB)

@Sherman:

right off the bat, I can see that you are jumping from the dataserver event, to a new state, and then straight back to the previous state... I suppose that would work, but it's way unnecessary, and state changes like that are going to be slow and painful compared to just repeating the test at the end of the dataserver event. in fact going in you know you have at least one test to do, so testing if you are done in state entry isn't needed (also it's bad form to have unenclosed if/or logic. if only one of two statements should run based on a test, they should be if/else'd)

you're still using a for list to pump out all your http posts in rapid fire order, when what you want to do is to push one out, wait for the return code, then increment the count, and build and push another... you can build a function to do it, and it'll need a global counter.

for a fun mind bender, build you sensor list, and when you're done, request the first av from the data server, when the dataserver returns, build your http post for that av, and send it, when the http response triggers, increment the counter and check it, then request the next av stuff you need from the dataserver if there are more, or go back to scanning for av's.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Paladin Pinion
The other one of 10
Join date: 3 Aug 2007
Posts: 191
12-20-2009 11:11
From: Void Singer
whoops, good catch, corrected above, that should've read != rather than == (which still looks like it should return a boolean but when it's used to compare lists, it actually compares their length and returns the difference, specifically (listA != listB) -> (lengthListA - lengthListB)


Thanks, I didn't know that. It's not obvious. Actually, it's kind of weird. It'd be great if someone who knows how could update the wiki to make a note of that. (hint hint) :)
_____________________
Mote Particle Script Generator - easier and faster than any HUD
Also: Paladin's Sunbeam. Up at dawn, gone by dusk, day and night sounds, fully configurable
See more at: www.paladinpinion.com
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-20-2009 12:23
Thanks for looking at the code. I tried making a global counter that can be checked after each http response but I failed miserable.

Since you are infinitely better than I am at this stuff, could you provide a little help with how to create a global counter?
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
12-20-2009 13:07
From: Sherman Gustafson
Thanks for looking at the code. I tried making a global counter that can be checked after each http response but I failed miserable.

Since you are infinitely better than I am at this stuff, could you provide a little help with how to create a global counter?

A counter is just a variable whose assigned value changes incrementally each time you go past a defined spot in a routine, as in ......

CODE

integer x = 10; // The variable "x" is the counter, starting with a value of 10
while (x > 0) // Keep going around this loop until x is <= 0
{
llSay(0, "The value of x is " + (string)x);
--x; // Every time the script reaches this point, x decreases by one.
}


You make a counter (or anything) global by defining it before entering the default state.
_____________________
It's hard to tell gender from names around here but if you care, Rolig = she. And I exist only in SL, so don't ask.... ;)

Look for my work in XStreetSL at
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-20-2009 15:53
From: Paladin Pinion
Thanks, I didn't know that. It's not obvious. Actually, it's kind of weird. It'd be great if someone who knows how could update the wiki to make a note of that. (hint hint) :)

one of these days when I get the time, I intend to revamp the whole operators section, so that they're categorized, and each has it's own page, showing it's action on different data types. there's just no way it'd all fit together and be readable in a single page. it's a time consuming project.

it is noted on the hacks page though.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-20-2009 16:22
a rough outline for the structure of an event moderated loop with a global counter in 2 calls.

CODE

integer gIntCount;
key gKeyQuery;

default{
/* fire sensor, fill lists, etc then go to next state */
}

state SendData{
state_entry(){
//-- set the counter
gIntCount = -llGetListLenght( agentKeyList );
//-- get the first av's data
gKeyQuery = llRequestAgentData( llList2Key( agentKeyList, gIntCount ), DATA_BORN );
}

dataserver( key vKeyQueryID, string vStrData ){
if (gKeyQuery == vKeyQueryID){
//-- add in your new data and build the info to send to the http post
gKeyQuery = llHTTPRequest( /*//-- your data to send for this av goes here --//*/ );
}
}

http_response( key request_id, integer status, list metadata, string body ){
if (gKeyQuery == vKeyQueryID){
if (++gIntCount){ //-- are we done?
//-- nope, get next one.
gKeyQuery = llRequestAgentData( llList2Key( agentKeyList, gIntCount ), DATA_BORN );
}else{
//-- we're done, go scan again, or something
}
}
}
}
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-20-2009 20:18
Hmmm I'll take a stab at this.

What does the variable 'vKeyQueryID' do? I noticed it isn't defined in your example.
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-20-2009 20:56
Okay... here's where I am at. Please look at the comments I added... I wasn't sure of how to add the collected data to the 'body' string that is sent with the http_request.

CODE

//Accounts for overlap of the 4 sensors... leave these values as they are
float x_min = 0;
float x_max = 128;
float y_min = 128;
float y_max = 256;

integer gIntCount;
key gKeyQuery;
list agentKeyList;
key vKeyQueryID;
string wrongGroupWarning = "You're in the wrong group!";

//Scan information... probably should leave this alone
float scanDistance = 96.0;
float scanRadius = PI;
float scanTimeout = 10.0;

//Lists of information about agents

list agentNameList;
list bornOnList;
list agentInfoList;
list agentPositionX;
list agentPositionY;
list agentDate;
list agentRotation;
list agentVelocity;

//Temp variable for current agent list index
integer agent;

//Count of http requests waiting to return
integer httpCount;

//List used for testing if we've seen this person before
list response;

default {
state_entry()
{
// fire sensor, fill lists, etc then go to next state
llSetText("SL Track Touch - New Version", <1,1,1>, 1.0);
llSensorRepeat("", NULL_KEY, AGENT, scanDistance, (2*(scanRadius)), scanTimeout);
}


sensor(integer total_number)
{
//Temp variable
key agentKey;
vector tempPos;
integer i;

for (i = 0; i < total_number; i++)
{
//Are they in the correct group?
if (llSameGroup(llDetectedKey(i)))
{
//Blank out lists
agentKeyList = [];
agentNameList = [];
agentInfoList = [];
agentPositionX = [];
agentPositionY = [];
agentDate = [];
agentRotation = [];
agentVelocity = [];
bornOnList = [];

llSetText("Scanning Island for Avatars", <1,1,1>, 1.0);

//Build lists
for(agent=0; agent < total_number; ++agent)
{
tempPos = llDetectedPos(agent);
agentKeyList += [llDetectedKey(agent)];
agentNameList += [llKey2Name(llDetectedKey(agent))];
agentInfoList += [llGetAgentInfo(llDetectedKey(agent))];
agentPositionX += [(integer)tempPos.x];
agentPositionY += [(integer)tempPos.y];
agentDate += llGetDate();
agentRotation += [llDetectedRot(agent)];
agentVelocity += [llDetectedVel(agent)];
}

state SendData;


}
//if not in group, stop them in their tracks
else {
llSay(0, wrongGroupWarning);}
}
}

}

state SendData {
state_entry(){
//-- set the counter to the amount of avatars detected
gIntCount = -llGetListLength(agentKeyList);
//-- get the first av's data
gKeyQuery = llRequestAgentData(llList2Key(agentKeyList, gIntCount), DATA_BORN);
}

dataserver(key vKeyQueryID, string vStrData){
if (gKeyQuery == vKeyQueryID){
string body;

//-- add in your new data and build the info to send to the http post

//THIS AREA NEEDS WORK!!! How do I add the data collected in the initial state to the 'body' string?

if (checkX >= x_min && checkX < x_max && checkY >= y_min && checkY < y_max ) {
gKeyQuery = llHTTPRequest("http://www.www.com/sltrack/sltrack.php",
[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],
body);
}

}
}

http_response(key request_id, integer status, list metadata, string body){
if (gKeyQuery == vKeyQueryID){
if (++gIntCount) { //-- are we done?
//-- nope, get next one.
gKeyQuery = llRequestAgentData(llList2Key(agentKeyList, gIntCount), DATA_BORN);
}
else {
state default;
}
}
}
}
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
12-20-2009 21:04
From: Sherman Gustafson
Hmmm I'll take a stab at this.

What does the variable 'vKeyQueryID' do? I noticed it isn't defined in your example.

In any dataserver event, it's the key of a request received from some calling event. In this example, when llRequestAgentData is invoked in the state_entry event, the request gets a key (gKeyQuery). Because there might be several data requests within a single script, it's usually smart to check to be sure you know which one is which. So, in this case, if (gKeyQuery == vKeyQueryID), do stuff.......

See http://wiki.secondlife.com/wiki/Dataserver
_____________________
It's hard to tell gender from names around here but if you care, Rolig = she. And I exist only in SL, so don't ask.... ;)

Look for my work in XStreetSL at
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-20-2009 21:17
From: Sherman Gustafson
Hmmm I'll take a stab at this.

What does the variable 'vKeyQueryID' do? I noticed it isn't defined in your example.

it stores a key that is returned when you make a dataserver or http request, so that when that event fires you can check and make sure you are getting the data you requested, and not data requested by another script for instance. it works like taking a number at a drug store... you get a number, they might motion someone up, if it's your number you get your order.

as for how to build your body for the http request, you can do it the same way you did originally since all that data is in global variables.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-21-2009 20:02
What I mean is, I don't need the for loop to build the list of info, do I?

In my original code, I used a for loop to build the list of info about each detected av... do I still need it?

CODE

//Build lists
for(agent=0; agent < total_number; ++agent)
{
tempPos = llDetectedPos(agent);
agentKeyList += [llDetectedKey(agent)];
agentNameList += [llKey2Name(llDetectedKey(agent))];
agentInfoList += [llGetAgentInfo(llDetectedKey(agent))];
agentPositionX += [(integer)tempPos.x];
agentPositionY += [(integer)tempPos.y];
agentDate += llGetDate();
agentRotation += [llDetectedRot(agent)];
agentVelocity += [llDetectedVel(agent)];
}
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-21-2009 20:33
Okay, disregard the last message... I think I figured it out on my own.

I have it working about 90% as it should. It collects the required data, sends it to the server, but then it gets stuck... it never returns to the default state so it can scan again.

Also, I haven't gotten to test this with multiple avs so it may not work any better than the old version :-/. I will test it with multiple avs as soon as I can.

Here is my code... please take a look and see what is causing it to not return to the default state:

CODE

//Accounts for overlap of the 4 sensors... leave these values as they are
float x_min = 0;
float x_max = 128;
float y_min = 128;
float y_max = 256;

integer gIntCount;
key gKeyQuery;
list agentKeyList;
key vKeyQueryID;
string wrongGroupWarning = "You're in the wrong group!";

//Scan information... probably should leave this alone
float scanDistance = 96.0;
float scanRadius = PI;
float scanTimeout = 10.0;

//Lists of information about agents

list agentNameList;
list bornOnList;
list agentInfoList;
list agentPositionX;
list agentPositionY;
list agentDate;
list agentRotation;
list agentVelocity;

//Temp variable for current agent list index
integer agent;



default {
state_entry()
{
// fire sensor, fill lists, etc then go to next state
llSetText("SL Track Touch - New Version", <1,1,1>, 1.0);
llSensorRepeat("", NULL_KEY, AGENT, scanDistance, (2*(scanRadius)), scanTimeout);
}


sensor(integer total_number)
{
//Temp variable
key agentKey;
vector tempPos;
integer i;

for (i = 0; i < total_number; i++)
{
//Are they in the correct group?
if (llSameGroup(llDetectedKey(i)))
{
//Blank out lists
agentKeyList = [];
agentNameList = [];
agentInfoList = [];
agentPositionX = [];
agentPositionY = [];
agentDate = [];
agentRotation = [];
agentVelocity = [];
bornOnList = [];

llSetText("Scanning Island for Avatars", <1,1,1>, 1.0);

//Build lists
for(agent=0; agent < total_number; ++agent)
{
tempPos = llDetectedPos(agent);
agentKeyList += [llDetectedKey(agent)];
agentNameList += [llKey2Name(llDetectedKey(agent))];
agentInfoList += [llGetAgentInfo(llDetectedKey(agent))];
agentPositionX += [(integer)tempPos.x];
agentPositionY += [(integer)tempPos.y];
agentDate += llGetDate();
agentRotation += [llDetectedRot(agent)];
agentVelocity += [llDetectedVel(agent)];
}

state SendData;


}
//if not in group, stop them in their tracks
else {
llSay(0, wrongGroupWarning);}
}
}

}

state SendData {
state_entry(){
//-- set the counter to the amount of avatars detected
gIntCount = -llGetListLength(agentKeyList);
//-- get the first av's data
gKeyQuery = llRequestAgentData(llList2Key(agentKeyList, gIntCount), DATA_BORN);
}

dataserver(key vKeyQueryID, string vStrData){
if (gKeyQuery == vKeyQueryID){
string body;
list infoSummary;
integer agentInfo;

body = "";
infoSummary = [];
agentInfo = llList2Integer(agentInfoList, gIntCount);

list timestamp = llParseString2List(llGetTimestamp(), ["T",":","Z"] , [] );
string hour = llList2String(timestamp, 1);
string minute = llList2String(timestamp, 2);
string second = llList2String(timestamp, 3);

integer checkX = llList2Integer(agentPositionX, gIntCount);
integer checkY = llList2Integer(agentPositionY, gIntCount);

if(agentInfo & AGENT_ALWAYS_RUN)
{
infoSummary += ["AGENT_ALWAYS_RUN"];
}
if(agentInfo & AGENT_ATTACHMENTS)
{
infoSummary += ["AGENT_ATTACHMENTS"];
}
if(agentInfo & AGENT_AWAY)
{
infoSummary += ["AGENT_AWAY"];
}
if(agentInfo & AGENT_BUSY)
{
infoSummary += ["AGENT_BUSY"];
}
if(agentInfo & AGENT_CROUCHING)
{
infoSummary += ["AGENT_CROUCHING"];
}
if(agentInfo & AGENT_FLYING)
{
infoSummary += ["AGENT_FLYING"];
}
if(agentInfo & AGENT_IN_AIR)
{
infoSummary += ["AGENT_IN_AIR"];
}
if(agentInfo & AGENT_MOUSELOOK)
{
infoSummary += ["AGENT_MOUSELOOK"];
}
if(agentInfo & AGENT_ON_OBJECT)
{
infoSummary += ["AGENT_ON_OBJECT"];
}
if(agentInfo & AGENT_SCRIPTED)
{
infoSummary += ["AGENT_SCRIPTED"];
}
if(agentInfo & AGENT_SITTING)
{
infoSummary += ["AGENT_SITTING"];
}
if(agentInfo & AGENT_TYPING)
{
infoSummary += ["AGENT_TYPING"];
}
if(agentInfo & AGENT_WALKING)
{
infoSummary += ["AGENT_WALKING"];
}

//Build the HTTP post variables
body = "name=" + llEscapeURL(llList2String(agentNameList, gIntCount)) +
"&time=" + hour + ":" + minute + ":" + second +
"&born=" + llEscapeURL(llList2String(bornOnList, gIntCount)) +
"&info=" + llEscapeURL(llList2CSV(infoSummary)) +
"&posx=" + (string)llList2Integer(agentPositionX, gIntCount) +
"&posy=" + (string)llList2Integer(agentPositionY, gIntCount) +
"&date=" + llEscapeURL(llList2CSV(agentDate)) +
"&objectclicked=" + llGetObjectName();

//Fire off the hit to the Web service and keep going

llSay(0, "Send: " +

"&name=" + llEscapeURL(llList2String(agentNameList, gIntCount)) + "\n" +
"&time=" + hour + ":" + minute + ":" + second + "\n" +
"&born=" + llEscapeURL(llList2String(bornOnList, gIntCount)) + "\n" +
"&info=" + llEscapeURL(llList2CSV(infoSummary)) + "\n" +
"&posx=" + llEscapeURL(llList2String(agentPositionX, gIntCount)) + "\n" +
"&posy=" + llEscapeURL(llList2String(agentPositionY, gIntCount)) + "\n" +
"&date=" + llEscapeURL(llList2CSV(agentDate)) + "\n" +
"&objectclicked=" + llGetObjectName()

);




//if (checkX >= x_min && checkX < x_max && checkY >= y_min && checkY < y_max ) {
gKeyQuery = llHTTPRequest("http://www.secondlifeworkshops.com/sltrack/sltrack.php",
[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],
body);
// }

}
}

http_response(key request_id, integer status, list metadata, string body){
if (gKeyQuery == vKeyQueryID){
if (++gIntCount) { //-- are we done?
//-- nope, get next one.
gKeyQuery = llRequestAgentData(llList2Key(agentKeyList, gIntCount), DATA_BORN);
}
else {
state default;
}
}
}
}
Sherman Gustafson
Registered User
Join date: 5 Sep 2007
Posts: 28
12-22-2009 19:49
Please?
1 2