Project Homebound

Selfbondage software and other kinky developments

Moderators: Riddle, Shannon SteelSlave

OrgasmAlley
****
Posts: 515
Joined: 18 Nov 2012, 17:43

Re: Project Homebound

Post by OrgasmAlley »

GeneralError wrote:I made a testrun for >3 hours. The magnet was constanty on and had to carry a little screw drive as weight. In my setup it is powered by the 3.3V of my ESP8266 board. The magnet was not even lukewarm.
Great to know. There's a review on Amazon for the same board indicating it "overheats" from an Arduino at 5VDC, so something to keep in mind.
thatthat21
**
Posts: 149
Joined: 07 Nov 2013, 03:23

Re: Project Homebound

Post by thatthat21 »

GeneralError wrote:
thatthat21 wrote:
GeneralError wrote:The magnet I ordered from wish https://www.wish.com/product/5b5cd464ff666512b9871a11. It is a complete little module that can be directly connected to microcontrollers without worrying about freewheeling diodes and ampere consumption. There are similar modules available in the typical shops.
Does this one get hot after running for a long time? With a lot of the round magnets they seem to get hot after running for a time. Not sure if they are just over volting them or what but just thought that I would ask about the temp. I might just have to get a few of them. I have a few extra https://www.particle.io/ cell and mesh versions showing up soon for another project so going to test with them as well.
I made a testrun for >3 hours. The magnet was constanty on and had to carry a little screw drive as weight. In my setup it is powered by the 3.3V of my ESP8266 board. The magnet was not even lukewarm.
Nice, and good to know.

Thank you
thatthat21
**
Posts: 149
Joined: 07 Nov 2013, 03:23

Re: Project Homebound

Post by thatthat21 »

GeneralError wrote:
thatthat21 wrote:
GeneralError wrote:Here is an image of the Node-RED control flow.
HB_Controlflow_600.jpg

Any way to get a better quality of that image? I can't seem to read any of the text in the flow.

Thank you
Here is a full size image of the flow. Off course there are lots of details hidden in the scripts and configuration settings within the nodes. But it might allow an impression on how a Node-RED flow can be designed.
HB_Controlflow_1100.jpg

Thank you for this, just helps seeing what another lay out kinda looks like. But understand the flow a better now, also found that my docker image did not have the dashboard active, so fixed that and have been playing around with it some.
thatthat21
**
Posts: 149
Joined: 07 Nov 2013, 03:23

Re: Project Homebound

Post by thatthat21 »

OrgasmAlley wrote:
GeneralError wrote:I made a testrun for >3 hours. The magnet was constanty on and had to carry a little screw drive as weight. In my setup it is powered by the 3.3V of my ESP8266 board. The magnet was not even lukewarm.
Great to know. There's a review on Amazon for the same board indicating it "overheats" from an Arduino at 5VDC, so something to keep in mind.
Yeah, that sounds about right, if you go to the upper volts like a lot people want to, they do seem to get hot. So the board I am work with only has a 3.3V so I should be good.
User avatar
GeneralError
**
Posts: 141
Joined: 16 Sep 2019, 15:30
Location: Germany

Re: Project Homebound

Post by GeneralError »

In the past few days I found some time to further enhance my blow job trainer. Now it can also detect deep throats.

I added a second photo transistor which only can be shaded when the dildo is seriously deep throated. Also I ported my software to an esp32 because it supports more than one adc (esp8266 only has one). After some additional coding for the additional photo transistor I made first test runs. But they were quite disappointing. The deep throat detection was not accurate and produced a lot of wrong positive and negative mistakes. It took me a challenging afternoon to fine tune the settings. It is not enough to just shade the sensors with a hand. They have to be inserted into the dildo, the lighting in the room has to be realistic and then the dildo has to really by deep throated. What can I say, I ended up with much better control over my gag reflex and quite hoarse :) But I found reliable minimum and maximum threshold values for brightness and timing and scam detection. And the result was worth the effort. The detection is very reliable now.
This is how the hardware looks now:
hbsbjHW_20_600.jpg
I also enhanced my homebound cockpit user interface. It displays accomplished deep throats now and the release mechanism checks a required minimum number of deep throats. Also I added some more flexibility to the session design by allowing to enable or disable specific "workouts".
HB_Cockpit_20_600.jpg
I'm looking forward now to do a real session with my hands cuffed to my back and no chance to escape without seriously sucking and deep throating this dildo. And I already have plans for the next enhancement, which will be the shock collar.
thatthat21
**
Posts: 149
Joined: 07 Nov 2013, 03:23

Re: Project Homebound

Post by thatthat21 »

Hmm, I wonder. Could to add in as an option that say you do X number of extra deep throats you get Y off you time, or something like that where if you do something extra you can get some kind of bonus.

Just a random thought.
zappy1
*
Posts: 31
Joined: 28 Dec 2019, 06:37

Re: Project Homebound

Post by zappy1 »

This is a really great idea. The trick to getting something like this is to hook it up with graphics. Without the graphics, the user will see it as a piece of plastic. Combine your idea of the sensor toy with a synchronized character, and then you are onto something revolutionary. Is there anybody here that is good with character creation software?

To be convincing to a user, a CAM would be needed to synchronize the character with the hardware and the user to judge distance, etc.

Character Creator 3 -- Easy and Powerful Game Character Creation Software
https://www.youtube.com/watch?v=G_USpgGegFQ

Image
User avatar
Shannon SteelSlave
Moderator
Posts: 6531
Joined: 03 Feb 2019, 19:49
Location: New England, USA

Re: Project Homebound

Post by Shannon SteelSlave »

Welcome to the forum, Zappy. Do you have skills in digital graphic arts? Send me a Private Message so we can chat. Shan'
Bondage is like a foreign film without subtitles. Only through sharing and practice can we hope to understand.
A Jedi uses bondage for knowledge and defense, never for attack.
I am so smart! I am so smart! S-M-R-T!....I, I mean S-M-A-R-T!
👠👠
zappy1
*
Posts: 31
Joined: 28 Dec 2019, 06:37

Re: Project Homebound

Post by zappy1 »

Shannon SteelSlave wrote:Welcome to the forum, Zappy. Do you have skills in digital graphic arts? Send me a Private Message so we can chat. Shan'
I am good with video design and AI text and language.

I created a few text to speech videos for free in a few minutes at https://www.voki.com. Paid is much better and can be made into downloadable video files. The most simple way to get custom video in a project is to create an mpeg/avi video file, then play it when appropriate. With in the code you would write "play xzy.mpeg." The best way is to have character like Microsoft Agent that is up continuously. The problem with those types is interoperability. The website I used would not be practical to use, it is just to demonstrate.

I wrote simple text to speech for these two that would fit a bondage project.
http://tinyurl.com/upxxmyx

http://tinyurl.com/vxcpecg

This one is with an audio file
http://tinyurl.com/v9u393p

Image
User avatar
GeneralError
**
Posts: 141
Joined: 16 Sep 2019, 15:30
Location: Germany

Re: Project Homebound

Post by GeneralError »

@zappy1 wow, cool. The graphics character intergration would lift it to a complete new level. At the moment I'm fully concentrated in adding more devices and implement more session flexibility. But the graphics direction is definetely worth for further investigation.
User avatar
Shannon SteelSlave
Moderator
Posts: 6531
Joined: 03 Feb 2019, 19:49
Location: New England, USA

Re: Project Homebound

Post by Shannon SteelSlave »

GeneralError wrote:@zappy1 wow, cool. The graphics character intergration would lift it to a complete new level. At the moment I'm fully concentrated in adding more devices and implement more session flexibility. But the graphics direction is definetely worth for further investigation.
It seems we have an enthusiastic graphics designer in the house.
Bondage is like a foreign film without subtitles. Only through sharing and practice can we hope to understand.
A Jedi uses bondage for knowledge and defense, never for attack.
I am so smart! I am so smart! S-M-R-T!....I, I mean S-M-A-R-T!
👠👠
User avatar
GeneralError
**
Posts: 141
Joined: 16 Sep 2019, 15:30
Location: Germany

Re: Project Homebound

Post by GeneralError »

I spent some effort in a reliable blow job detection and also deep throat detection. I want to share my approach here since I think it is quite reliable now and a good base for discussion or further improvement. As several threads here show, the self bondage blow job action is liked by many as part of their sessions as it is one of my favourites.
According to the general architecture of my Homebound system, every device is communicating via mqtt protocol (message queue telemetry protocol) with the central control unit. And so does my blow job sensor. Every ~3.2 secs it sends a message that looks like this:

Code: Select all

{
  "frequency" : 2.441735,
  "duration" : 3200,
  "minimum" : 0,
  "maximum" : 1846,
  "dt_accomplished" : true,
  "dt_duration" : 4023,
  "mqttClientId" : "hbsbjt"
}
The meaning of this sample is: Within the last 3.2 secs the delinquent performed a blow job with an average of 2.44 sucks/second. Also the delinquent finished a deep throat action that took about ~4 secs.

To gain this values I implanted two SFH300 photo transistors into a transparent dildo. The first photo transistor sits close to the tip of the dildo and allows blow job detection. The second photo transitor sits ~15 cm away from the tip. It allows deep throat detection.

The major challenge was the blow job detection. The photo transistors do often deliver measurement errors or the room is too dark or the detection can be scammed by just covering the dildo with something. My first approach that just compares a measured value with a hardcoded threshold to destinguish between bright=out and dark=in was not reliable. After some google searches and forum readings I found a better approach: Fast fourier transformation for frequency analysis. This sounds very complicated but it isn't, since there are libraries available that are easy and ready to use. The trick is to sample a series of measurements and let the fft library analyze it to determine a dominant frequency for the series.
I choosed 32 samples with measurements every 0.1 sec. So one sample window is 3.2 secs long.
Besides the fft analysis I introduced several more checks like i.e. a threshold that checks that the maximum value and the minimum value have to differ by a certain percentage.
The result of this implementation turned out to be quite reliable. While the returned frequency is not very accurate but at least reacts nicely to the suck speed. But if a frequency value greater zero is returned, the reliablity is high, that the delinquent really performed a proper blow job. (see function getCurrentDominantFrequency())

The deep throat detection was easier. There is no need to detect movement. An implementation with hard coded thresholds worked. The program makes use of the values of both photo transistors and also checks some timing conditions. The logic is coded within function checkDt(...)

Here is the source code, made for ESP32 microcontroller and two SFH300 photo transistors:

Code: Select all


/****************************
   ESP WiFi
 ***************************/

char ssid[32] = "myHomeboundSsid";				// SSID of the wlan to connect to
char pwd[64] = "secretPassword";				// password for wlan


#include <WiFi.h>
#include <WiFiClient.h>

WiFiClient espClient;



/****************************
   MQTT & Json
 ***************************/

#include <stdlib.h>
#include <ArduinoJson.h>

#include "PubSubClient.h"
#define MQTT_BROKER_IP    "192.168.111.1"		// ip number of the mqtt broker
#define MQTT_BROKER_PORT  1883					// port number (1883 is standard)
#define MQTT_CLIENT_ID    "hbsbjt"
#define MQTT_TOPIC "homebound/" MQTT_CLIENT_ID
#define MQTT_TOPIC_SENSOR "tele/" MQTT_TOPIC "/sensor"
#define MQTT_TOPIC_CMND "cmnd/" MQTT_TOPIC "/"
#define MQTT_TOPIC_CMND_SUBSCRIBE MQTT_TOPIC_CMND "#"
#define MQTT_TOPIC_CMND_STATUS MQTT_TOPIC_CMND "status"
#define MQTT_TOPIC_STATUS "stat/" MQTT_TOPIC "/status"



// Json Strukturen
StaticJsonDocument<256> jsonDoc;
char buffer[256];
PubSubClient mqttClient(espClient);



/****************************
   Fourier
 ***************************/

#include "arduinoFFT.h"
// 32 samples, one every 0.1 sec => 3.2 secs window
#define SAMPLES 32                  //Must be a power of 2
#define SAMPLING_FREQUENCY 10       //Hz, must be less than 10000 due to ADC
#define WAIT_BETWEEN_SAMPLES_MS (1000/SAMPLING_FREQUENCY)

arduinoFFT FFT = arduinoFFT(); // create FFT object

double vReal[SAMPLES]; //Real part of FFT array
double vImag[SAMPLES]; //Imaginary part of FFT aray


/****************************
   BJ detection
 ***************************/

// we compare the max and min walues of the sample values
// the diff of both must exceed a threshhold or the sampling is considered to just measure sensor fluctuations
// the max must be at least MINMAX_DIFF_PROZ percent higher than the min
int vMin = 4095; // esp32 12-Bit ad
int vMax = 0;
#define MINMAX_DIFF_PROZ 200

// a minimum value for the maximum is required. Otherways it might be very dark an a min=10 and a max=80 are 800%
// difference but it is just a fluctuation in the dark.
// Better is a max>400 to consider it as a serious measurement
#define BJ_DARKNESSLIMIT 400


/****************************
   DT detection
 ***************************/
boolean dt_started = false;
int dt_startMillis = 0;
boolean dt_accomplished = false;
int dt_duration = 0;
const int dt_maxduration = 15000;
const int dt_minduration = 2000;
#define DT_DARKNESSLIMIT 200


/****************************
   photo transistor
 ***************************/

// esp8266: const int ANALOG_IN_1 = A0; // Analog input pin
const int ANALOG_IN_1 = 32; // Analog input #1 on pin GPIO32 (adc1 ch4) (for bj detection) 
const int ANALOG_IN_2 = 33; // Analog input #2 on pin GPIO33 (adc1 ch6) (for dt detection)

/****************************
   misc
 ***************************/
const int LED_BUILTIN = 2;
const int ANALOGMAXIMUM = 4095; // 4095 for esp32 with 12-Bit ADC (1023 for esp8266 with 10Bit ADC)


void setup_wlan() {
  Serial.println("init wlan....");

  // setting network parameters
  //WiFi.hostname(host);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pwd);

  // connecting
  Serial.print("connecting device to ");
  Serial.println(ssid);
  while (WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.print(".");
  }
  Serial.print("\n got IP: ");
  Serial.println(WiFi.localIP());
}

void setup_mqtt() {
  Serial.println("init mqtt");
  Serial.print("my mqtt broker is: ");
  Serial.print(MQTT_BROKER_IP);
  Serial.print(":");
  Serial.println(MQTT_BROKER_PORT);
  Serial.print("MQTT_MAX_PACKET_SIZE=");
  Serial.println(MQTT_MAX_PACKET_SIZE);

  mqttClient.setServer(MQTT_BROKER_IP, MQTT_BROKER_PORT);
}

void setup_fft() {
  Serial.println("init FFT");
  Serial.print("init fft. SAMPLES=");
  Serial.print(SAMPLES);
  Serial.print(" SAMPLING_FREQUENCY=");
  Serial.println(SAMPLING_FREQUENCY);
}


void setup() {

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  Serial.println("\n");
  Serial.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
  Serial.println("initializing device ");
  Serial.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

  digitalWrite(LED_BUILTIN, LOW);
  delay(200);
  digitalWrite(LED_BUILTIN, HIGH);

  setup_wlan();

  Serial.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
  digitalWrite(LED_BUILTIN, LOW);
  delay(200);
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(LED_BUILTIN, LOW);
  delay(200);
  digitalWrite(LED_BUILTIN, HIGH);

  setup_mqtt();

  Serial.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

  setup_fft();

  Serial.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}



void loop() {

  // give mqtt client some time to receive messages
  mqttClient.loop();

  int startMillis = millis();
  sampling_loop();

  double freq = getCurrentDominantFrequency();
  //Serial.println("");
  int duration = millis() - startMillis;
  char*jsonMsg = createJson_telemetry(freq, duration);
  mqttPublish(MQTT_TOPIC_SENSOR, jsonMsg);

  digitalWrite(LED_BUILTIN, LOW);
  delay(20);
  digitalWrite(LED_BUILTIN, HIGH);

}

void sampling_loop() {
  vMin = ANALOGMAXIMUM;    // will hold the minimum measurement after sampling
  vMax = 0;                // will hold the maximum measurement after sampling

  for (int i = 0; i < SAMPLES; i++)
  {
    // measurement
    int val1 = analogRead(ANALOG_IN_1);
    int val2 = analogRead(ANALOG_IN_2);

    checkDt(val1, val2); 

    // adjust min and max
    if (val1 < vMin) {
      vMin = val1;
    }
    if (val1 > vMax) {
      vMax = val1;
    }

    // save measured value in array
    vReal[i] = val1;
    vImag[i] = 0;

    //Serial.print(val1);
    //Serial.print(",");
    //Serial.println(val2);
    //Serial.print("\t");
    delay(WAIT_BETWEEN_SAMPLES_MS);
  }
}

void checkDt(int val1, int val2) {

    if (dt_started) {
        // we are already in dt state

        // DT ending
        if (val2 > DT_DARKNESSLIMIT) {
            dt_duration = millis() - dt_startMillis;
            if (dt_duration > dt_maxduration) {
                Serial.print("DT too long ");
                Serial.println(dt_duration);
                resetDt();
                return;
            }
            if (dt_duration < dt_minduration) {
                Serial.print("DT too short ");
                Serial.println(dt_duration);
                resetDt();
                return;
            }

            dt_accomplished = true;
            dt_started = false;
            Serial.print("DT accomplished ");                
            Serial.print("- dt_duration=");
            Serial.println(dt_duration / 1000);    
            return;
        }

        // inconsistent data
        if (val1 > BJ_DARKNESSLIMIT) {
            Serial.println("DT scam ");                
            resetDt();
            return;
        }

        // dt ongoing
        return;
    }

    // no dt -> no dt
    if (val1 > BJ_DARKNESSLIMIT) {
        return;
    }
    if (val2 > DT_DARKNESSLIMIT) {
        return;
    }

    // no dt -> dt
    Serial.print("DT start at ");
    Serial.println(val2);                
    resetDt();
    dt_started = true;
    dt_startMillis = millis();   
}

void resetDt() {
    dt_started = false;
    dt_startMillis = 0;
    dt_accomplished = false;
    dt_duration = 0;
}


double getCurrentDominantFrequency() {
  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
  //FFT.DCRemoval(vReal, SAMPLES);

  //the most dominant frequency.
  double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);

  // how many percent is the max bigger than the min?
  int proz = 0.0;
  if (vMin > 0.0) {
    // avoid div / 0
    proz = ((vMax - vMin) * 100) / vMin;
  } else {
    // if min = 0 any max exceeds the percentage
    proz = MINMAX_DIFF_PROZ;
  }
  
  // if percentage is too small, ignore value
  if (proz < MINMAX_DIFF_PROZ) {
    peak = 0.0;
    Serial.print("BJ: percentage too low: ");
    Serial.println(proz);
  }

  // or if max is too small (too dark), ignore value
  if (vMax < BJ_DARKNESSLIMIT) {
    peak = 0.0;
    Serial.print("BJ: max too dark: ");
    Serial.println(vMax);
  }


  return peak;

}



char* createJson_telemetry(double freq, int duration) {
  jsonDoc.clear();
  jsonDoc["frequency"] = freq;
  jsonDoc["duration"] = duration;
  jsonDoc["minimum"] = vMin;
  jsonDoc["maximum"] = vMax;
  
  if (dt_accomplished) {
    jsonDoc["dt_accomplished"] = dt_accomplished;
    jsonDoc["dt_duration"] = dt_duration;
    resetDt();
  } else {
    jsonDoc["dt_accomplished"] = dt_accomplished;
    jsonDoc["dt_duration"] = 0;
  }
  
  jsonDoc["mqttClientId"] = MQTT_CLIENT_ID;

  serializeJson(jsonDoc, buffer);
  return buffer;
}

char* createJson_status() {
  jsonDoc.clear();
  jsonDoc["status"] = "ok";
  jsonDoc["uptime"] = millis();
  jsonDoc["mqttClientId"] = MQTT_CLIENT_ID;

  serializeJson(jsonDoc, buffer);
  return buffer;
}



void mqttPublish(char* topic, char* json) {
  // check mqtt broker connection
  if (!mqttClient.connected()) {
    mqttReconnect();
  }


  Serial.print(topic);
  Serial.print(" -> ");
  int success = mqttClient.publish(topic, (byte*)json, strlen(json), false);
  if ( ! success) {
    Serial.println("ERROR: mqtt publish failed");
  }
  Serial.println(json);
}

void mqttReconnect() {
  while (!mqttClient.connected()) {
    Serial.print("reconnecting mqtt client ");
    Serial.print(MQTT_CLIENT_ID);
    Serial.print(" to mqtt broker ");
    Serial.print(MQTT_BROKER_IP);
    Serial.print(" -> ");

    if (!mqttClient.connect(MQTT_CLIENT_ID)) {
      Serial.print("Error: ");
      Serial.print(mqttClient.state());
      Serial.println(" will retry in 5 secs.");
      delay(5000);
    }
    Serial.print("ok, mqtt state: ");
    Serial.println(mqttClient.state());

    Serial.print("subscribing to ");
    Serial.println(MQTT_TOPIC_CMND_SUBSCRIBE);
    if (!mqttClient.subscribe(MQTT_TOPIC_CMND_SUBSCRIBE)) {
      Serial.print("Warning: Subscription failed. topic: ");
      Serial.println(MQTT_TOPIC_CMND_SUBSCRIBE);
    }

  }
  mqttClient.setCallback(mqttSubscribeReceive);
}

void mqttSubscribeReceive(char* topic, byte* nutzdaten, unsigned int laenge) {

  if (strcmp(MQTT_TOPIC_CMND_STATUS, topic) == 0) {
    char* jsonMsg = createJson_status();
    mqttPublish(MQTT_TOPIC_STATUS, jsonMsg);
    return;
  }

  Serial.println("mqtt received unexpected topic: ");
  Serial.println(topic);

  Serial.print("payload: ");
  for (int i = 0; i < laenge; i++) {
    Serial.print(char(nutzdaten[i]));
  }
  Serial.println("");
}
I wish a kinky 2020 to everyone here
Cheers
General Alex Error
zappy1
*
Posts: 31
Joined: 28 Dec 2019, 06:37

Re: Project Homebound

Post by zappy1 »

The code seems to be in Java or Groovy. What did you use, and why? Why did not not use Python which is much simpler?
User avatar
GeneralError
**
Posts: 141
Joined: 16 Sep 2019, 15:30
Location: Germany

Re: Project Homebound

Post by GeneralError »

zappy1 wrote:The code seems to be in Java or Groovy. What did you use, and why? Why did not not use Python which is much simpler?
The code is c/c++. Since this program is meant for a microcontrollers, specific restrictions apply. I'm using Arduino-Ide as development environment, which has the by far biggest eco system and so a huge number of reusable libraries, resources, communities, forums. One should have a very good reason to go for a different language. MicroPython would be at least a doable option, but is a niche system. I heard rumors of a Java VM for microcontrollers, from Groovy on microcontrollers I never heard something.
My focus is to get the functionality working, so Arduino Ide with c/c++ is clearly the best way.
thatthat21
**
Posts: 149
Joined: 07 Nov 2013, 03:23

Re: Project Homebound

Post by thatthat21 »

For the butt plug did you use an inflatable plug and just remove the inflater bulb and hose and put the thermal probe inside it that way?

On the dildo, it looks like it was a normal suction cup base type, but looks like you insert a tube of some sort to install the light sensors? If so, how did you go about getting that inserted?
Post Reply