]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_parking: Add dialplan function for lot channel
authorJoshua Elson <joshelson@gmail.com>
Fri, 6 Jul 2018 22:00:06 +0000 (16:00 -0600)
committerRichard Mudgett <rmudgett@digium.com>
Tue, 10 Jul 2018 16:03:01 +0000 (11:03 -0500)
This commit adds a new function to res_parking.

This function, PARK_GET_CHANNEL allows the retrieval
of the channel name of the channel occupying the parking slot.

ASTERISK-22825 #close

Change-Id: Idba6ae55b8a53f734238cb3d995cedb95c0e7b74

res/parking/parking_bridge_features.c
res/parking/parking_controller.c
res/parking/res_parking.h

index 2770233332b65a2fb1bc212739beddd79f4630d1..cbc23fac1b2e34590eba1e75942ea3595f582ee5 100644 (file)
 #include "asterisk/astobj2.h"
 #include "asterisk/logger.h"
 #include "asterisk/pbx.h"
+#include "asterisk/app.h"
 #include "asterisk/bridge.h"
 #include "asterisk/bridge_internal.h"
 #include "asterisk/bridge_channel.h"
 #include "asterisk/bridge_features.h"
+#include "asterisk/conversions.h"
 #include "asterisk/features.h"
 #include "asterisk/say.h"
 #include "asterisk/datastore.h"
 #include "asterisk/core_local.h"
 #include "asterisk/causes.h"
 
+/*** DOCUMENTATION
+       <function name="PARK_GET_CHANNEL" language="en_US">
+               <synopsis>
+                       Get the channel name of an occupied parking space in a parking lot.
+               </synopsis>
+                       <syntax>
+                               <parameter name="parking_space" required="true">
+                               </parameter>
+                               <parameter name="parking_lot" required="true">
+                               </parameter>
+                       </syntax>
+               <description>
+                       <para>This function returns the channel of the specified parking space
+                               if the parking lot space is occupied.</para>
+                       </description>
+       </function>
+***/
+
 struct parked_subscription_datastore {
        struct stasis_subscription *parked_subscription;
 };
@@ -704,6 +724,60 @@ void parking_set_duration(struct ast_bridge_features *features, struct parked_us
        }
 }
 
+/*! \brief  Dial plan function to get the parking lot channel of an occupied parking lot */
+static int func_get_parkingslot_channel(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
+{
+       RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
+       RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
+       unsigned int space = 0;
+       const char *content = NULL;
+
+       AST_DECLARE_APP_ARGS(args,
+               AST_APP_ARG(parking_space);
+               AST_APP_ARG(parking_lot);
+               AST_APP_ARG(other);
+       );
+
+       /* Parse the arguments. */
+       AST_STANDARD_APP_ARGS(args, data);
+
+       if (args.argc < 2) {
+               /* Didn't receive enough arguments to do anything */
+               ast_log(LOG_ERROR, "Usage: %s(<parking_space>,<parking_lot>)\n",
+                       function);
+               return -1;
+       }
+
+       lot = parking_lot_find_by_name(args.parking_lot);
+       if (!lot) {
+               ast_log(LOG_ERROR, "Could not find parking lot: '%s'\n", args.parking_lot);
+               return -1;
+       }
+
+       if (!ast_strlen_zero(args.parking_space)) {
+               if (ast_str_to_uint(args.parking_space, &space) != 0) {
+                       ast_log(LOG_ERROR, "value '%s' for parking_space argument is invalid. Must be an integer greater than 0.\n",
+                               args.parking_space);
+                       return -1;
+               }
+       }
+
+       pu = parking_lot_inspect_parked_user(lot, space);
+       if (!pu) {
+               return -1;
+       }
+
+       content = ast_channel_name(pu->chan);
+       ast_copy_string(buf, content, len);
+
+       return 0;
+}
+
+static struct ast_custom_function getparkingslotchannel_function = {
+       .name = "PARK_GET_CHANNEL",
+       .read = func_get_parkingslot_channel,
+};
+
 struct ast_parking_bridge_feature_fn_table parking_provider = {
        .module_version = PARKING_MODULE_VERSION,
        .module_name = __FILE__,
@@ -717,12 +791,15 @@ void unload_parking_bridge_features(void)
 {
        ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_PARKCALL);
        ast_parking_unregister_bridge_features(parking_provider.module_name);
+       ast_custom_function_unregister(&getparkingslotchannel_function);
 }
 
 int load_parking_bridge_features(void)
 {
        parking_provider.module = AST_MODULE_SELF;
 
+       ast_custom_function_register(&getparkingslotchannel_function);
+
        if (ast_parking_register_bridge_features(&parking_provider)) {
                return -1;
        }
index 9e9e540cd8ab51d4c918b2e75aeaf6522301c117..365acddb7f640756512669a9d6706c1c277589c4 100644 (file)
@@ -163,6 +163,23 @@ static int retrieve_parked_user_targeted(void *obj, void *arg, int flags)
        return 0;
 }
 
+struct parked_user *parking_lot_inspect_parked_user(struct parking_lot *lot, int target)
+{
+       struct parked_user *user;
+
+       if (target < 0) {
+               user = ao2_callback(lot->parked_users, 0, NULL, NULL);
+       } else {
+               user = ao2_callback(lot->parked_users, 0, retrieve_parked_user_targeted, &target);
+       }
+
+       if (!user) {
+               return NULL;
+       }
+
+       return user;
+}
+
 struct parked_user *parking_lot_retrieve_parked_user(struct parking_lot *lot, int target)
 {
        RAII_VAR(struct parked_user *, user, NULL, ao2_cleanup);
index 3c34e5c92e2644b5bd16186ffbbbd849fda27f91..79fb97f34b143c0853fd5f3f471aa9b2d53d33a8 100644 (file)
@@ -195,6 +195,19 @@ struct ast_bridge *parking_lot_get_bridge(struct parking_lot *lot);
  */
 int parking_lot_get_space(struct parking_lot *lot, int target_override);
 
+/*!
+ * \brief Determine if there is a parked user in a parking space and return it if there is.
+ *
+ * \param lot Parking lot being pulled from
+ * \param target If < 0   search for the first occupied space in the parking lot
+ *               If >= 0  Only pull from the indicated target
+ *
+ * \retval NULL if no parked user could be pulled from the requested parking lot at the requested parking space
+ * \retval reference to the requested parked user
+ *
+ */
+struct parked_user *parking_lot_inspect_parked_user(struct parking_lot *lot, int target);
+
 /*!
  * \since 12.0.0
  * \brief Determine if there is a parked user in a parking space and pull it from the parking lot if there is.