From dcafb54c8eb3ca54873e56f565c736842465b192 Mon Sep 17 00:00:00 2001 From: Julien Cabillot Date: Mon, 24 Apr 2017 01:57:17 +0200 Subject: [PATCH] =?UTF-8?q?on=20adapte=20le=20code=20=C3=A0=20alarmclock?= =?UTF-8?q?=20(simplification),=20changement=20des=20channels=20de=20statu?= =?UTF-8?q?s/command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arduino/alarmclock/alarmclock.cpp | 323 +------------------- arduino/alarmclock/alarmclock.exemple.h | 160 +--------- home-assistant/conf_light.d/alarmclock.yaml | 8 +- home-assistant/configuration.yaml | 8 +- 4 files changed, 20 insertions(+), 479 deletions(-) diff --git a/arduino/alarmclock/alarmclock.cpp b/arduino/alarmclock/alarmclock.cpp index d403eba..9389faa 100644 --- a/arduino/alarmclock/alarmclock.cpp +++ b/arduino/alarmclock/alarmclock.cpp @@ -7,25 +7,12 @@ #include "alarmclock.h" - -# TODO : tout reste à faire, ceci est la copie de mqttfastledmenu à adapter - // LED -// En déplaçant ces vars dans le .h + init dans le setup, cylon crash au moment du premier retour ?! float brightness = LED_BRIGHTNESS_DEFAULT; int color = LED_COLOR_DEFAULT; -int speed = LED_SPEED_DEFAULT; CRGB leds[LED_NUM]; -String ledEffect = LED_EFFECT_ERROR; boolean ledState = false; -// WIFI -WiFiClient espClient; - -// MQTT -char message_buff[100]; -PubSubClient client(espClient); - void setup() { Serial.begin(SERIAL_SPEED); @@ -38,8 +25,6 @@ void setup() /* brightness = LED_BRIGHTNESS_DEFAULT; color = LED_COLOR_DEFAULT; - speed = LED_SPEED_DEFAULT; - ledEffect = LED_EFFECT_ERROR; ledState = false; */ @@ -47,11 +32,6 @@ void setup() ledBlackAll(); FastLED.setBrightness(brightness); - //////////////////////////////// ColorPalette /////////////////////////////// - currentPalette = RainbowColors_p; - currentBlending = LINEARBLEND; - //////////////////////////////// ColorPalette /////////////////////////////// - // MQTT client.setServer(MQTT_SERVER, MQTT_PORT); client.setCallback(callbackMQTT); @@ -98,16 +78,12 @@ void testConnectMQTT() if (client.connect("ESP8266Client", MQTT_USER, MQTT_PASS)) { Serial.print("OK\nSend Current State"); mqttSendState(); - mqttSendSpeedState(); mqttSendBrightnessState(); - mqttSendEffectState(); mqttSendColorState(); Serial.print("OK\nSubscribe"); client.subscribe(MQTT_LED_COMMAND); - client.subscribe(MQTT_LED_EFFECT_COMMAND); client.subscribe(MQTT_LED_BRIGHTNESS_COMMAND); - client.subscribe(MQTT_LED_SPEED_COMMAND); client.subscribe(MQTT_LED_COLOR_COMMAND); Serial.println(" OK"); @@ -143,11 +119,6 @@ void callbackMQTT(char* topic, byte* payload, unsigned int length) ledBlackAll(); } mqttSendState(); - } else if (stopic == MQTT_LED_EFFECT_COMMAND) { - // Si on ne repasse pas tout à noir, cela peut faire des effets surprenants - ledBlackAll(); - ledEffect = msgString; - mqttSendEffectState(); } else if (stopic == MQTT_LED_BRIGHTNESS_COMMAND) { brightness = msgString.toInt(); FastLED.setBrightness(brightness); @@ -160,9 +131,6 @@ void callbackMQTT(char* topic, byte* payload, unsigned int length) color=((red <<16)|(green <<8)|blue); mqttSendColorState(); - } else if (stopic == MQTT_LED_SPEED_COMMAND) { - speed = msgString.toInt(); - mqttSendSpeedState(); } } @@ -171,13 +139,6 @@ void mqttSendState() client.publish(MQTT_LED_STATE, (ledState) ? "ON": "OFF", true); } -void mqttSendEffectState() -{ - char buff[ledEffect.length() + 1]; - ledEffect.toCharArray(buff, ledEffect.length() + 1); - client.publish(MQTT_LED_EFFECT_STATE, buff, true); -} - void mqttSendBrightnessState() { char buff[4]; @@ -185,13 +146,6 @@ void mqttSendBrightnessState() client.publish(MQTT_LED_BRIGHTNESS_STATE, buff, true); } -void mqttSendSpeedState() -{ - char buff[4]; - itoa(speed, buff, 10); - client.publish(MQTT_LED_SPEED_STATE, buff, true); -} - void mqttSendColorState() { int red = color>>16 & 0xFF; @@ -213,95 +167,6 @@ void ledBlackAll() FastLED.show(); } -/** -* Effet Cylon : défilement d'une simple led sur le strip aller/retour. -* Pour faire plus sympas on ajoute une lueur autour, avec une lumière atténué. -*/ -void ledCylon() -{ - for (int i = 0; i < LED_NUM; i++) { - client.loop(); - - if (ledEffect != LED_EFFECT_CYLON) { - return; - } - - if ((i - 3) >= 0) { - leds[i - 3] = CRGB::Black; - } - if ((i - 2) >= 0) { - /* - * Se lit 128/256 d'intensité lumineuse actuelle - * https://github.com/FastLED/FastLED/wiki/Pixel-reference#dimming-and-brightening-colors - */ - leds[i - 2] = color; - leds[i - 2].fadeLightBy(220); - } - if ((i - 1) >= 0) { - leds[i - 1] = color; - leds[i - 1].fadeLightBy(200); - } - - leds[i] = color; - - if ((i + 1) <= LED_NUM) { - leds[i + 1] = color; - // Je suis volontairement un peu moins puissant sur l'avant - // pour donner un effet de trainée sur l'arrière - leds[i + 1].fadeLightBy(249); - } - - FastLED.delay(1000 / speed); - } - // Il faut nettoyer certaines cases avant la prochaine loop - if ((LED_NUM - 2) >= 0) { - leds[LED_NUM - 2] = color; - leds[LED_NUM - 2].fadeLightBy(220); - } - if ((LED_NUM - 1) >= 0 ) { - leds[LED_NUM - 1] = CRGB::Black; - } - FastLED.show(); - - // led[0] et led[255] sont gérées par la loop précédante - for (int i = LED_NUM - 1; i >= 0; i--) { - client.loop(); - if (ledEffect != LED_EFFECT_CYLON) { - return; - } - if ((i - 1) >= 0) { - leds[i - 1] = color; - leds[i - 1].fadeLightBy(249); - } - - leds[i] = color; - - if ((i + 1) <= LED_NUM) { - leds[i + 1] = color; - leds[i + 1].fadeLightBy(200); - } - - if ((i + 2) <= LED_NUM) { - leds[i + 2] = color; - leds[i + 2].fadeLightBy(220); - } - - if ((i + 3) <= LED_NUM) { - leds[i + 3] = CRGB::Black; - } - FastLED.delay(1000 / speed); - } - // Il faut nettoyer certaines cases avant la prochaine loop - if (1 <= LED_NUM) { - leds[1] = color; - leds[1].fadeLightBy(220); - } - if (2 <= LED_NUM) { - leds[2] = CRGB::Black; - } - FastLED.show(); -} - /** * Utilise pour indiquer une erreur sur la reception de l'effet. */ @@ -315,7 +180,7 @@ void ledError() } } - FastLED.delay(1000 / speed); + FastLED.delay(1000); } /** @@ -331,183 +196,11 @@ void ledFullColor() //float breath = (exp(sin(millis() / 2000.0 * map(speed, 0, 255, 50, 300)/100 * PI)) - 0.3678794) * 108.4; float breath = (exp(sin(millis() / 4000.0 * PI)) - 0.3678794) * 108.4; - // J'ai essayé de mapper breath sur 3;brightness pour ne pas eteindre les leds, - // mais l'effet est plus saccadé - fill_solid(leds, LED_NUM, color); FastLED.setBrightness(breath); FastLED.show(); } -///////////////////// FastLED-3.1.5/examples/ColorPalette ///////////////////// -void ledColorPattern() -{ - ChangePalettePeriodically(); - - static uint8_t startIndex = 0; - startIndex = startIndex + 1; /* motion speed */ - - FillLEDsFromPaletteColors(startIndex); - - FastLED.delay(1000 / speed); -} - -void FillLEDsFromPaletteColors(uint8_t colorIndex) -{ - uint8_t brightness = 255; - - for( int i = 0; i < LED_NUM; i++) { - leds[i] = ColorFromPalette( - currentPalette, - colorIndex, - brightness, - currentBlending - ); - colorIndex += 3; - } -} - -// There are several different palettes of colors demonstrated here. -// -// FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p, -// OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p. -// -// Additionally, you can manually define your own color palettes, or you can write -// code that creates color palettes on the fly. All are shown here. -void ChangePalettePeriodically() -{ - uint8_t secondHand = (millis() / 1000) % 60; - static uint8_t lastSecond = 99; - - if( lastSecond != secondHand) { - lastSecond = secondHand; - /* - if (secondHand == 0) { currentPalette = RainbowColors_p; currentBlending = LINEARBLEND; } - if (secondHand == 10) { currentPalette = RainbowStripeColors_p; currentBlending = NOBLEND; } - if (secondHand == 15) { currentPalette = RainbowStripeColors_p; currentBlending = LINEARBLEND; } - if (secondHand == 20) { SetupPurpleAndGreenPalette(); currentBlending = LINEARBLEND; } - if (secondHand == 25) { SetupTotallyRandomPalette(); currentBlending = LINEARBLEND; } - if (secondHand == 30) { SetupBlackAndWhiteStripedPalette(); currentBlending = NOBLEND; } - if (secondHand == 35) { SetupBlackAndWhiteStripedPalette(); currentBlending = LINEARBLEND; } - if (secondHand == 40) { currentPalette = CloudColors_p; currentBlending = LINEARBLEND; } - if (secondHand == 45) { currentPalette = PartyColors_p; currentBlending = LINEARBLEND; } - if (secondHand == 50) { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND; } - if (secondHand == 55) { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; } - */ - if (secondHand == 0) { SetupPurpleAndGreenPalette(); currentBlending = LINEARBLEND; } - if (secondHand == 10) { SetupBlackAndWhiteStripedPalette(); currentBlending = LINEARBLEND; } - if (secondHand == 30) { currentPalette = CloudColors_p; currentBlending = LINEARBLEND; } - if (secondHand == 40) { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; } - } -} - -/* -// This function fills the palette with totally random colors. -void SetupTotallyRandomPalette() -{ - for (int i = 0; i < 16; i++) { - currentPalette[i] = CHSV(random8(), 255, random8()); - } -} -*/ - -// This function sets up a palette of black and white stripes, -// using code. Since the palette is effectively an array of -// sixteen CRGB colors, the various fill_* functions can be used -// to set them up. -void SetupBlackAndWhiteStripedPalette() -{ - // 'black out' all 16 palette entries... - fill_solid(currentPalette, 16, CRGB::Black); - // and set every fourth one to white. - currentPalette[0] = CRGB::White; - currentPalette[4] = CRGB::White; - currentPalette[8] = CRGB::White; - currentPalette[12] = CRGB::White; -} - -// This function sets up a palette of purple and green stripes. -void SetupPurpleAndGreenPalette() -{ - CRGB purple = CHSV(HUE_PURPLE, 255, 255); - CRGB green = CHSV(HUE_GREEN, 255, 255); - CRGB black = CRGB::Black; - - currentPalette = CRGBPalette16( - green, green, black, black, - purple, purple, black, black, - green, green, black, black, - purple, purple, black, black - ); -} -///////////////////// FastLED-3.1.5/examples/ColorPalette ///////////////////// - -/////////////////// FastLED-3.1.5/examples/ColorTemperature /////////////////// -void colorTemp() -{ - // draw a generic, no-name rainbow - static uint8_t starthue = 0; - fill_rainbow(leds + 5, LED_NUM - 5, --starthue, 20); - - // Choose which 'color temperature' profile to enable. - uint8_t secs = (millis() / 1000) % (DISPLAYTIME * 2); - if (secs < DISPLAYTIME) { - FastLED.setTemperature(TEMPERATURE_1 ); // first temperature - leds[0] = TEMPERATURE_1; // show indicator pixel - } else { - FastLED.setTemperature(TEMPERATURE_2 ); // second temperature - leds[0] = TEMPERATURE_2; // show indicator pixel - } - - // Black out the LEDs for a few secnds between color changes - // to let the eyes and brains adjust - if((secs % DISPLAYTIME) < BLACKTIME) { - memset8(leds, 0, LED_NUM * sizeof(CRGB)); - } - - FastLED.show(); - FastLED.delay(8); -} -/////////////////// FastLED-3.1.5/examples/ColorTemperature /////////////////// - -//////////////////////// FastLED-3.1.5/examples/Fire202 /////////////////////// -void fire() -{ - // Array of temperature readings at each simulation cell - static byte heat[LED_NUM]; - - // Step 1. Cool down every cell a little - for (int i = 0; i < LED_NUM; i++) { - heat[i] = qsub8(heat[i], random8(0, ((COOLING * 10) / LED_NUM) + 2)); - } - - // Step 2. Heat from each cell drifts 'up' and diffuses a little - for (int k= LED_NUM - 1; k >= 2; k--) { - heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3; - } - - // Step 3. Randomly ignite new 'sparks' of heat near the bottom - if (random8() < SPARKING ) { - int y = random8(7); - heat[y] = qadd8(heat[y], random8(160,255)); - } - - // Step 4. Map from heat cells to LED colors - for (int j = 0; j < LED_NUM; j++) { - CRGB color = HeatColor( heat[j]); - int pixelnumber; - if (gReverseDirection) { - pixelnumber = (LED_NUM - 1) - j; - } else { - pixelnumber = j; - } - leds[pixelnumber] = color; - } - - FastLED.delay(1000 / speed); -} -//////////////////////// FastLED-3.1.5/examples/Fire202 /////////////////////// - void loop() { // MQTT testConnectMQTT(); @@ -517,18 +210,6 @@ void loop() { if (!ledState) { FastLED.delay(1000); } else { - if (ledEffect == LED_EFFECT_CYLON) { - ledCylon(); - } else if (ledEffect == LED_EFFECT_FULLRED) { - ledFullColor(); - } else if (ledEffect == LED_EFFECT_COLORPATTERN) { - ledColorPattern(); - } else if (ledEffect == LED_EFFECT_COLORTEMP) { - colorTemp(); - } else if (ledEffect == LED_EFFECT_FIRE) { - fire(); - } else { - ledError(); - } + ledFullColor(); } } diff --git a/arduino/alarmclock/alarmclock.exemple.h b/arduino/alarmclock/alarmclock.exemple.h index a256919..7f37bf0 100644 --- a/arduino/alarmclock/alarmclock.exemple.h +++ b/arduino/alarmclock/alarmclock.exemple.h @@ -1,180 +1,42 @@ #define SERIAL_SPEED 115200 -# TODO : tout reste à faire, ceci est la copie de mqttfastledmenu à adapter - // LED #define LED_NUM 300 #define LED_PIN 5 // = D1 #define LED_CHIPSET WS2812B #define LED_COLOR_ORDER GRB #define LED_BRIGHTNESS_DEFAULT 96 -#define LED_SPEED_DEFAULT 120 #define LED_COLOR_DEFAULT CRGB::Red -#define LED_EFFECT_CYLON "cylon" -#define LED_EFFECT_COLORPATTERN "colorp" -#define LED_EFFECT_COLORTEMP "colort" -#define LED_EFFECT_FIRE "fire" -#define LED_EFFECT_FULLRED "full" -#define LED_EFFECT_ERROR "error" - // WIFI #define WIFI_SSID "XXX" #define WIFI_PASSWORD "XXX" +WiFiClient espClient; + // MQTT #define MQTT_SERVER "XXX" #define MQTT_PORT 1883 #define MQTT_USER "XXX" #define MQTT_PASS "XXX" -#define MQTT_LED_COMMAND "strip1/switch" -#define MQTT_LED_STATE "strip1/status" -#define MQTT_LED_EFFECT_COMMAND "strip1/effect/switch" -#define MQTT_LED_EFFECT_STATE "strip1/effect/status" -#define MQTT_LED_BRIGHTNESS_COMMAND "strip1/brightness/switch" -#define MQTT_LED_BRIGHTNESS_STATE "strip1/brightness/status" -#define MQTT_LED_SPEED_COMMAND "strip1/speed/switch" -#define MQTT_LED_SPEED_STATE "strip1/speed/status" -#define MQTT_LED_COLOR_COMMAND "strip1/color/switch" -#define MQTT_LED_COLOR_STATE "strip1/color/status" +#define MQTT_LED_COMMAND "alarmclock/switch" +#define MQTT_LED_STATE "alarmclock/status" +#define MQTT_LED_BRIGHTNESS_COMMAND "alarmclock/brightness/switch" +#define MQTT_LED_BRIGHTNESS_STATE "alarmclock/brightness/status" +#define MQTT_LED_COLOR_COMMAND "alarmclock/color/switch" +#define MQTT_LED_COLOR_STATE "alarmclock/color/status" + +char message_buff[100]; +PubSubClient client(espClient); void setupWifi(); void testConnectMQTT(); void callbackMQTT(char* topic, byte* payload, unsigned int length); void mqttSendState(); -void mqttSendEffectState(); void mqttSendBrightnessState(); -void mqttSendSpeedState(); void mqttSendColorState(); void ledBlackAll(); -void ledCylon(); void ledError(); void ledFullColor(); -///////////////////////////////// ColorPalette -// This example shows several ways to set up and use 'palettes' of colors -// with FastLED. -// -// These compact palettes provide an easy way to re-colorize your -// animation on the fly, quickly, easily, and with low overhead. -// -// USING palettes is MUCH simpler in practice than in theory, so first just -// run this sketch, and watch the pretty lights as you then read through -// the code. Although this sketch has eight (or more) different color schemes, -// the entire sketch compiles down to about 6.5K on AVR. -// -// FastLED provides a few pre-configured color palettes, and makes it -// extremely easy to make up your own color schemes with palettes. -// -// Some notes on the more abstract 'theory and practice' of -// FastLED compact palettes are at the bottom of this file. -CRGBPalette16 currentPalette; -TBlendType currentBlending; - -extern CRGBPalette16 myRedWhiteBluePalette; -extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM; - -// This example shows how to set up a static color palette -// which is stored in PROGMEM (flash), which is almost always more -// plentiful than RAM. A static PROGMEM palette like this -// takes up 64 bytes of flash. -const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM = -{ - CRGB::Red, - CRGB::Gray, // 'white' is too bright compared to red and blue - CRGB::Blue, - CRGB::Black, - - CRGB::Red, - CRGB::Gray, - CRGB::Blue, - CRGB::Black, - - CRGB::Red, - CRGB::Red, - CRGB::Gray, - CRGB::Gray, - CRGB::Blue, - CRGB::Blue, - CRGB::Black, - CRGB::Black -}; - -void ledColorPattern(); -void FillLEDsFromPaletteColors(uint8_t colorIndex); -void ChangePalettePeriodically(); -void SetupTotallyRandomPalette(); -void SetupBlackAndWhiteStripedPalette(); -void SetupPurpleAndGreenPalette(); -//////////////////////////////////////////////// ColorTemperature -// THIS EXAMPLE demonstrates the second, "color temperature" control. -// It shows a simple rainbow animation first with one temperature profile, -// and a few seconds later, with a different temperature profile. -// -// The first pixel of the strip will show the color temperature. -// -// HELPFUL HINTS for "seeing" the effect in this demo: -// * Don't look directly at the LED pixels. Shine the LEDs aganst -// a white wall, table, or piece of paper, and look at the reflected light. -// -// * If you watch it for a bit, and then walk away, and then come back -// to it, you'll probably be able to "see" whether it's currently using -// the 'redder' or the 'bluer' temperature profile, even not counting -// the lowest 'indicator' pixel. -// -// -// FastLED provides these pre-conigured incandescent color profiles: -// Candle, Tungsten40W, Tungsten100W, Halogen, CarbonArc, -// HighNoonSun, DirectSunlight, OvercastSky, ClearBlueSky, -// FastLED provides these pre-configured gaseous-light color profiles: -// WarmFluorescent, StandardFluorescent, CoolWhiteFluorescent, -// FullSpectrumFluorescent, GrowLightFluorescent, BlackLightFluorescent, -// MercuryVapor, SodiumVapor, MetalHalide, HighPressureSodium, -// FastLED also provides an "Uncorrected temperature" profile -// UncorrectedTemperature; - -#define TEMPERATURE_1 Tungsten100W -#define TEMPERATURE_2 OvercastSky -// How many seconds to show each temperature before switching -#define DISPLAYTIME 20 -// How many seconds to show black between switches -#define BLACKTIME 3 -void colorTemp(); -///////////////////////////////////////////////Fire202 -bool gReverseDirection = false; -// This basic one-dimensional 'fire' simulation works roughly as follows: -// There's a underlying array of 'heat' cells, that model the temperature -// at each point along the line. Every cycle through the simulation, -// four steps are performed: -// 1) All cells cool down a little bit, losing heat to the air -// 2) The heat from each cell drifts 'up' and diffuses a little -// 3) Sometimes randomly new 'sparks' of heat are added at the bottom -// 4) The heat from each cell is rendered as a color into the leds array -// The heat-to-color mapping uses a black-body radiation approximation. -// -// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). -// -// This simulation scales it self a bit depending on NUM_LEDS; it should look -// "OK" on anywhere from 20 to 100 LEDs without too much tweaking. -// -// I recommend running this simulation at anywhere from 30-100 frames per second, -// meaning an interframe delay of about 10-35 milliseconds. -// -// Looks best on a high-density LED setup (60+ pixels/meter). -// -// -// There are two main parameters you can play with to control the look and -// feel of your fire: COOLING (used in step 1 above), and SPARKING (used -// in step 3 above). -// -// COOLING: How much does the air cool as it rises? -// Less cooling = taller flames. More cooling = shorter flames. -// Default 50, suggested range 20-100 -#define COOLING 55 - -// SPARKING: What chance (out of 255) is there that a new spark will be lit? -// Higher chance = more roaring fire. Lower chance = more flickery fire. -// Default 120, suggested range 50-200. -#define SPARKING 120 -void fire(); diff --git a/home-assistant/conf_light.d/alarmclock.yaml b/home-assistant/conf_light.d/alarmclock.yaml index 00f2088..ec746fc 100644 --- a/home-assistant/conf_light.d/alarmclock.yaml +++ b/home-assistant/conf_light.d/alarmclock.yaml @@ -1,7 +1,7 @@ - platform: "mqtt" name: "alarmclock" retain: true - command_topic: "strip1/switch" - state_topic: "strip1/status" - rgb_command_topic: "strip1/color/switch" - rgb_state_topic: "strip1/color/status" + command_topic: "alarmclock/switch" + state_topic: "alarmclock/status" + rgb_command_topic: "alarmclock/color/switch" + rgb_state_topic: "alarmclock/color/status" diff --git a/home-assistant/configuration.yaml b/home-assistant/configuration.yaml index d124096..51376a5 100644 --- a/home-assistant/configuration.yaml +++ b/home-assistant/configuration.yaml @@ -1,5 +1,3 @@ -# TODO : tout reste à faire, ceci est la copie de mqttfastledmenu à adapter - homeassistant: customize: !include_dir_merge_named "conf_customize.d/" @@ -10,7 +8,7 @@ mqtt: username: "XXX" password: "XXX" -light: !include_dir_merge_list "conf_light.d/" -automation: !include_dir_merge_list "conf_automation.d/" -group: !include_dir_merge_named "conf_group.d/" +light: !include_dir_merge_list "conf_light.d/" +automation: !include_dir_merge_list "conf_automation.d/" +group: !include_dir_merge_named "conf_group.d/" script: !include_dir_merge_named "conf_script.d/"